let's start with the code
class MyClass:
def __init__(self):
self.elemplusone = None
self.elemplustwo = None
self.data = self.generate_data()
def generate_data(self):
for elem in range(10):
yield elem+1, elem+2
I need to get the first and the second element of generator. Right now, I'm calling it outside the class after creating an object:
a_generator = MyClass()
c = next(a_generator.data)
elemplusone = c[0]
elemplustwo = c[1]
but I need them to be specified (as separate generators) in the class and I can't create two generator methods.
Thanks
I also don't quite understand what you mean exactly. But does this help you?
class MyClass:
def __init__(self):
self.data = self.generate_data()
self.update_elements()
def update_elements(self):
self.elemplusone, self.elemplustwo = [x for x in next(self.data)]
def generate_data(self):
for elem in range(10):
print("Yielded")
yield elem + 1, elem + 2
a_generator = MyClass()
a_generator.elemplusone is 1 and a_generator.elemplustwo is 2.
Now you could call a_generator.update_elements() to yield your elements again and continue in your generator. Please let me know if this helps you. Good luck!
Related
My __repr__ method works fine using objects created in it's class, but with objects that were created with the help of importing a library and using methods from it, it only represented the memory address...
from roster import student_roster #I only got the list if students from here
import itertools as it
class ClassroomOrganizer:
def __init__(self):
self.sorted_names = self._sort_alphabetically(student_roster)
def __repr__(self):
return f'{self.get_combinations(2)}'
def __iter__(self):
self.c = 0
return self
def __next__(self):
if self.c < len(self.sorted_names):
x = self.sorted_names[self.c]
self.c += 1
return x
else:
raise StopIteration
def _sort_alphabetically(self,students):
names = []
for student_info in students:
name = student_info['name']
names.append(name)
return sorted(`your text`names)
def get_students_with_subject(self, subject):
selected_students = []
for student in student_roster:
if student['favorite_subject'] == subject:
selected_students.append((student['name'], subject))
return selected_students
def get_combinations(self, r):
return it.combinations(self.sorted_names, r)
a = ClassroomOrganizer()
# for i in a:
# print(i)
print(repr(a))
I tried displaying objects that don't rely on anther library, and they dispayed properly.
The issue I was facing was linked to me not understanding the nature of the object. itertools.combinations is an iterable, and in order to represent the values stored I needed to either:
unpack it inside a variable like:
def get_combinations(self, r):
*res, = it.combinations(self.sorted_names, r)
return res
Iter through it inside a loop and leave the original code intact like
for i in a.get_combinations(2):
print(i)
I prefer the second solution
Learning python from Udacity. Exercise is mentioned below. I cannot see where output 'None' is coming from. Is there something about classes that I am missing ? Thx in advance
Output is always
0
None
======= CODE BEGIN ==============
"""You can use this class to represent how classy someone
or something is.
"Classy" is interchangable with "fancy".
If you add fancy-looking items, you will increase
your "classiness".
Create a function in "Classy" that takes a string as
input and adds it to the "items" list.
Another method should calculate the "classiness"
value based on the items.
The following items have classiness points associated
with them:
"tophat" = 2
"bowtie" = 4
"monocle" = 5
Everything else has 0 points.
Use the test cases below to guide you!"""
class Classy(object):
def __init__(self):
self.items = []
self.classiness = 0
def getClassiness(self):
print(self.classiness)
def createList(self):
self.items.append(item)
def addItem(self, item):
if item=="tophat":
self.classiness+=2
elif item=="bowtie":
self.classiness+=4
elif item=="monocle":
self.classiness+=5
else:
self.classiness+=0
return self.classiness
# Test cases
me = Classy()
# Should be 0
print(me.getClassiness())
Your method getClassiness() is printing and the caller is also printing.
Maybe you meant to return a value rather than printing?
def getClassiness(self):
return self.classiness
class Classy(object):
def __init__(self):
self.items = []
self.classiness = 0
def getClassiness(self):
return self.classiness
def createList(self):
self.items.append(item)
def addItem(self, item):
if item=="tophat":
self.classiness+=2
elif item=="bowtie":
self.classiness+=4
elif item=="monocle":
self.classiness+=5
else:
self.classiness=0
Test cases
me = Classy()
Should be 0
print(me.getClassiness())
I have the following example in which the next method of a class is supposed to return the values from two generators:
class Test():
def __next__(self):
g1, g2 = self._gen1(), self._gen2()
return next(g1), next(g2)
def _gen1(self):
i = 0
while True:
yield i
i += 2
def _gen2(self):
i = 1
while True:
yield i
i += 2
However, when I call next for this class, the values are not incremented.
>>> t = Test()
>>> next(t)
>>> (0, 1)
>>> next(t)
>>> (0, 1)
What is wrong? Is there a more eloquent way to write this class?
Although I have no idea what you are trying to accomplish, here is a cleaned up version which (I think) does what you want.
class Test():
def __init__(self):
self.g1 = self._gen2()
self.g2 = self._gen1()
def __next__(self):
return next(self.g1), next(self.g2)
def _gen1(self):
i = 0
while True:
yield i
i += 2
def _gen2(self):
i = 1
while True:
yield i
i += 2
t = Test()
print(next(t))
print(next(t))
print(next(t))
Your code doesn't work because it recreates the generator functions every time __next__() is called, which effectively resets them back to their initial state before their next next() values are returned:
def __next__(self):
g1, g2 = self._gen1(), self._gen2() # Don't do this here.
return next(g1), next(g2)
You can fix that by adding an __init__() method and initializing them in it:
class Test:
def __init__(self):
self.g1, self.g2 = self._gen1(), self._gen2() # Initialize here.
def __next__(self):
return next(self.g1), next(self.g2)
...
A more eloquent and slightly more concise way to do it which likewise will avoid the problem would be to use the builtin zip() function to create an "iterator of generators" that will return pairs of next values from each generator every time it's called. Another advantage is it's very easy to extend to handle even more generators simply just changing the __init__() method.
Here's what I mean:
class Test:
def __init__(self):
self.generators = zip(self._gen1(), self._gen2())
def __next__(self):
return next(self.generators)
def _gen1(self):
i = 0
while True:
yield i
i += 2
def _gen2(self):
i = 1
while True:
yield i
i += 2
t = Test()
for _ in range(3):
print(next(t))
Output:
(0, 1)
(2, 3)
(4, 5)
This question already has answers here:
Function changes list values and not variable values in Python [duplicate]
(7 answers)
Closed 7 years ago.
The code below imports a linked list from LinkedQfile and creates a list object with some node objects.
If I run this code the output from check_something() becomes CD .
I thought linked_list in check_something() would become a local object inside the function and since I'm not assigning whatever I'm returning to anything it wouldn't change, that is I would expect the output ABCD. This is obviously not the case so I'm wondering if someone could explain to me what is going on here?
If linked_list was a global variable I would expect this outcome, my guess is that the return statements in each function returns some information to the object but I have no idea how and why! (I got the code from a lecture note and it works just like I want it to, I just want to know why!)
from LinkedQFile import LinkedQ
def check_something(linked_list):
check_first_element(linked_list)
check_second_element(linked_list)
print(linked_list)
def check_first_element(linked_list):
word = linked_list.dequeue()
if word == "A":
return
def check_second_element(linked_list):
word = linked_list.dequeue()
if word == "B":
return
def main():
list = LinkedQ()
list.enqueue("A")
list.enqueue("B")
list.enqueue("C")
list.enqueue("D")
check_something(list)
main()
And if needed, the LinkedQFile:
class Node:
def __init__(self, x, next= None):
self._data = x
self._next = next
def getNext(self):
return self._next
def setNext(self, next):
self._next = next
def getValue(self):
return self._data
def setValue(self, data):
self._data = data
class LinkedQ:
def __init__(self):
self._first = None
self._last = None
self._length = 0
def __str__(self):
s = ""
p = self._first
while p != None:
s = s + str(p.getValue())
p = p.getNext()
return s
def enqueue(self, kort):
ny = Node(kort)
if self._first == None:
self._first = ny
else:
self._last = self._first
while self._last.getNext():
self._last = self._last.getNext()
self._last.setNext(ny)
self._length += 1
def dequeue(self):
data = self._first.getValue()
self._first = self._first.getNext()
self._length = self._length - 1
return data
You're right about linked_list being a local variable, but just because a variable is local doesn't mean it can't reference something that isn't. In order for it to do what you expected, it would need to copy your entire linked list every time you pass it to a function, which wouldn't make sense.
Here's a simple example that illustrates the idea of a shared object. In this example, an empty list is created and assigned to a. Then a is assigned to b. This does not copy the list. Instead, there is a single list, referenced by both a and b. When it is modified, through either a or b, both a and b reflect the change:
>>> a = []
>>> b = a
>>> a.append("x")
>>> a
['x']
>>> b
['x']
>>>
The same thing is happening with your class objects. In fact, your linked lists wouldn't work at all if it didn't.
When I try to enter the code below, I get [None, None] printed on the console rather than the expected [3, 3] and was wondering what would help to fix this.
class Blah(object):
def track(self,dot):
self.dot = dot
class Second(Blah):
def __init__(self,arg):
self.blocky = []
x = 0
while x < 2:
self.blocky.append(Blah.track(self,arg))
x += 1
bleh = Second(3)
print bleh.blocky
Among other more minor issues, your track method doesn't return anything, so you're passing the returned value of a function that returns nothing (None in other words) into that list.
The following worked for me:
class Blah(object):
def track(self, dot):
self.dot = dot
return self.dot
class Second(Blah):
def __init__(self, arg):
self.blocky = []
x = 0
while x < 2:
self.blocky.append(self.track(arg))
x += 1
Blah.track doesn't have a return statement, so it returns None.
You could fix this by doing:
class Blah(object):
def track(self, dot):
self.dot = dot
return dot
Also, you're calling Blah.track(self, dot) when you could just be calling self.track(dot), since self is a Second, which is a subclass of Blah.
That might look like this:
class Second(Blah):
def __init__(self,arg):
self.blocky = []
x = 0
while x < 2:
self.blocky.append(self.track(arg))
x += 1
The track method isn't returning anything. Perhaps you meant this?
def track(self, dot):
self.dot = dot
return dot
Also, since Second inherits from Blah you can replace
Blah.track(self, arg)
with
self.track(arg)