Python return result is not alike "N()" - python

I made the method name is slide. and it must return the reference of it. Then, What should I do?.
First, I made this function like:
class N:
def slide(self, i):
#do something
return self
This slide method must return "N()" but "<~~ obejct at x0000>"

Definitely depends on your calling code. But this, for example, will work as expected to return a reference to an instantiated object N:
class N:
i = 1
def slide(self, i):
self.i = i;
return self
n = N()
print(n.i) # 1
r = n.slide(2)
print(r.i) # 2

Related

How can I modify my __repr__ to respresent correctly?

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

Overloading addition function and the result creates a new type of class

I need to overload the addition function so that it takes in the first point and the end point as the left and right side of the equation and outputs the equation. This is what my code looks right now. I'm not sure how to involve the line class?
import math
class Point:
'''Class that creates points. Attributes: Eastings and Northings'''
def __init__(self,x,y):
self.eastings = x
self.northings = y
def getCoords(self):
self.coords = (self.eastings,self.northings)
return self.coords
def setCoords(self,other_x,other_y):
self.eastings = float(other_x)
self.northings = float(other_y)
def __str__(self):
return f"{self.eastings},{self.northings}"
def __add__(self,new_point):
pass
#creates a line (new class)
class Line(Point):
'''Class that creates line object based on two points'''
def __init__(self,start,end):
self.start = start #Type:Point (x1,y1)
self.end = end #Type:Point (x2,y2)
self.latitude = abs(self.end.eastings - self.start.eastings)
self.departure = abs(self.end.northings - self.start.northings)
self.distance = math.sqrt((self.latitude)**2 + (self.departure)**2)
self.azimuth = math.degrees(math.atan2(self.departure,self.latitude))
def __getitem__(self,key):
if key == 0:
ans = self.start
elif key == 1:
ans = self.end
else:
print("invalid index")
return ans
#test code
a = Point(0,0)
b = Point(1,1)
c = Point(1,0.5)
line1 = a+b
print((type(line1))
The test code is supposed to print out the type as class line.
There's nothing that says the __add__() method has to return a the same type as the instance — which means you could this:
class Point:
...
def __add__(self, other):
if isinstance(other, Point):
return Line(self, other) # Line from this Point to the other.
else:
raise TypeError(f"Can't add a non-Point to a Point}")
Be careful doing this however, because the Line class will inherit the method (so you probably need to modify its version of it).
Add a self.getCoords() call to your Point.__init__() method.
Add return Line(self, new_point) to your Point.__add__() method.
Testing:
a = Point(0,0)
b = Point(1,1)
c = Point(1,0.5)
line1 = a+b
print(type(line1)) # I have removed a round bracket on the left
Output: <class '__main__.Line'>
In case you want to run a block of code, where a function/method has not one line in it, you have to add a pass to it. Otherwise you will get an error, because the structure requires it. Or you comment the function declaration out.

How to create a next method for a class when the next method is supposed to return the values of two generators?

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)

GDB pretty-printing: returning string from a children()'s iterator, but displayed as a char[]

I have a handy class that I use to allow me to easily add a set of "summariser" functions to a GDB pretty printer (for example, a Rect class could have an [Area] field, computed by Python). it then prints all the existing children as well, so you can see everything at once.
class SummaryAndFieldIterator:
"""
Iterator to first go through a list of summariser functions,
then display all the fields in the object in order
"""
def __init__ (self, obj, summaries):
self.count = 0
self.obj = obj;
self.summaries = summaries;
self.keys = sorted(obj.type.iterkeys())
def __iter__(self):
return self
def __next__(self):
if (self.count >= len(self.keys) + len(self.summaries)):
raise StopIteration
elif self.count < len(self.summaries):
name, retVal = self.summaries[self.count](self.obj)
# FIXME: this doesn't seem to work when a string is returned
# in retVal?
result = "[%s]" % name, retVal
else:
field = self.count - len(self.summaries)
result = self.keys[field], self.obj[self.keys[field]]
self.count += 1
return result
next = __next__
class MyObjectPrinter:
def __init__(self, val):
self.val = val
def get_int(self):
return "meaning", 42
def get_string(self):
return "hoopiness", "Forty-two"
def children(self):
return SummaryAndFieldIterator(self.val, [self.get_string])
This works very well for the summarisers which return numeric values, but for strings, it ends up displaying as an array, so that I get
NAME VALUE
myobj {..}
|-->[meaning] 42
|-->[hoopiness]
|-->[0] 'F'
|-->[1] 'o'
.....
|-->real_field 34234
This is presumably becuase the string that comes from
name, retVal = self.summaries[self.count](self.obj)
does not generate a sufficiently "stringy" gdb.Value object when it is returned by SummaryAndFieldIterator's __next__ method. Adjusting the display_hint() method of MyObjectPrinter doesn't seem to have any effect (but I doubt it would, as this is the child, not the object).
Anyone know how to return a string from the children() iterator and get it to display as a string?
Okay, apparently this may be a bug related to the way that GDB/MI communicates with pretty-printers, Bugzilla created here : https://sourceware.org/bugzilla/show_bug.cgi?id=18282

issues with calling a superclass's method and adding the returned value to an array

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)

Categories

Resources