Problem using super().__init__() when doing class inheritance - python

I have this simple code to calculate the height and width of a rectangle defining 3 classes:
PointL which creates 1 point with x and y attributes.
Polyline: which just contains 4 points from the class Point.
Rectangle: which is supposed to call the points from Polyline and return the height and width.
However I'm getting 0.0 for both height and width all the time. I have to use the super() method for this.
class Point:
def __init__(self, x=0.0, y=0.0):
self.__x = x
self.__y = y
def set_x(self, x):
self.__x = x
def set_y(self, y):
self.__y = y
def set(self, x, y):
self.__x = x
self.__y = y
def get_x(self):
return self.__x
def get_y(self):
return self.__y
def __str__(self): # <---- New __str__ method
return "Point("+str(self.__x)+", "+str(self.__y)+")"
x = property(get_x, set_x)
y = property(get_y, set_y)
class Polyline:
def __init__(self, n=None):
self.__p0 = Point()
self.__p1 = Point()
self.__p2 = Point()
self.__p3 = Point()
self.__n = n
def get_p0(self):
return self.__p0
def get_p1(self):
return self.__p1
def get_p2(self):
return self.__p2
def get_p3(self):
return self.__p3
def set_p0(self, p):
self.__p0 = p
def set_p1(self, p):
self.__p1 = p
def set_p2(self, p):
self.__p2 = p
def set_p3(self, p):
self.__p3 = p
def __str__(self):
return "Line 1 from: " + str(self.__p0) + " to " + str(self.__p2) + "\n" + "Line 2 from: " + str(self.__p1) + " to " + str(self.__p3) + "\n"
p0 = property(get_p0, set_p0)
p1 = property(get_p1, set_p1)
p2 = property(get_p2, set_p2)
p3 = property(get_p3, set_p3)
class Rectangle(Point):
def __init__(self, n=None, height=0.0, width=0.0):
super().__init__(n) # <--- Call inherited constructor of Point-class
self.__height = height
self.__width = width
def get_height(self):
p0 = super().get_p0()
p1 = super().get_p1()
self.__height = p0.y - p1.y
def get_width(self):
p0 = super().get_p0()
p1 = super().get_p1()
self.__width = p0.x - p1.x
def __str__(self):
return "Rectangle dimensions: \n" + "Width: " + str(self.__width) + ", " + "Height: " + str(self.__height) + "\n"
width = property(get_width)
height = property(get_height)
These are my inputs:
polyline = Polyline()
polyline.p0.x = 0.0
polyline.p0.y = 2.0
polyline.p1.x = 3.0
polyline.p1.y = 4.0
print(polyline)
rectangle = Rectangle()
print(rectangle)
And these are my outputs:
Line 1 from: Point(0.0, 2.0) to Point(0.0, 4.0)
Line 2 from: Point(3.0, 4.0) to Point(3.0, 2.0)
Rectangle dimensions:
Width: 0.0, Height: 0.0

Related

Python: 2 classes importing each other causes an error?

So I have the following directory setup:
Project
Misc Packages and Modules
resources
shapes
Rectangle.py
Rectangle2D.py
Rectangle is just a conceptual rectangle that isn't ever drawn (using Tkinter) but is there for collision and bounds. Rectangle2D is used as a subclass to draw or fill a Rectangle. The classes before I got the error were as followed:
Rectangle.py
class Rectangle(object):
_x = -1
_y = -1
_w = -1
_h = -1
def __init__(self, x, y, w, h):
self._x = x
self._y= y
self._w = w
self._h = h
def intersects(self, other):
if isinstance(other, Rectangle):
if (self._x + self._w) > other._x > self._x and (self._y + self._h) > other._y > self._y:
return True
elif (self._x + self._w) > (other._x + other._w) > self._x and (self._y + self._h) > other._y > self._y:
return True
elif (self._x + self._w) > other._x > self._x and (other._y + other._h) > self._y > other._y:
return True
elif (self._x + self._w) > (other._x + other._w) > self._x and (other._y + other._h) > self._y > other._y:
return True
else:
return False
else:
return False
def __eq__(self, other):
return self._x == other._x and self._y == other._y and self._w == other._w and self._h == other._h
Rectangle2D.py
from tkinter import Canvas
from .Rectangle import Rectangle
class Rectangle2D(Rectangle):
def __init__(self, x, y, w, h):
super(Rectangle2D, self).__init__(x, y, w, h)
self.color = 'black'
self.id = None
def draw_rect(self, canvas):
if isinstance(canvas, Canvas):
self.id = canvas.create_rectangle(self._x, self._y, self._x + self._w, self._y + self._h, outline=self.color)
return True
else:
print("Improper Parameter Type")
return False
def fill_rect(self, canvas):
if isinstance(canvas, Canvas):
self.id = canvas.create_rectangle(self._x, self._y, self._x + self._w, self._y + self._h, fill=self.color)
return True
else:
print("Improper Parameter Type")
return False
Everything was working fine until I wanted to add a method to Rectangle.py that would return a Rectangle2D.py. This record the following line to be added to Rectangle.py in addition to the method:
from .Rectangle2D import Rectangle2D
This resulted in the following error:
from .Rectangle import Rectangle
ImportError: cannot import name 'Rectangle'
What is causing this error and how do I fix it?
Also note I am running Python 3.6

Create a picklable Python class

I am trying to create some custom Python classes for my application. When I try to debug my code I can not pick the instances of my custom classes, I receive the error "Object XXX is not picklable".
I found this page https://docs.python.org/3/library/pickle.html#what-can-be-pickled-and-unpickled but I don't understand how I should implement the methods that make my class picklable.
For example how would you modify the following classes so that I can pick instances of them?
class Point3D:
def __init__ (self, x, y, z):
self.x = x
self.y = y
self.z = z
def move(self, vector):
self.x += vector.x
self.y += vector.y
self.z += vector.z
return
def isValidPoint(self):
isNotValid = False
isNotValid = math.isnan(self.x) or math.isnan(self.y) or math.isnan(self.z)
return not isNotValid
And
class PointCloud3D:
def __init__ (self):
self.points = []
def getNumberOfPoints(self):
return len(self.points)
def addPoint(self, point):
self.points.append(point)
return
def addPointCloud3D(self, additionalPointCloud3D):
for self.point in additionalPointCloud3D:
self.addPoint(point)
def getCloudCenter(self):
numberOfPoints = self.getNumberOfPoints()
centersSumX = 0
centersSumY = 0
centersSumZ = 0
for point in self.points:
centersSumX = centersSumX + point.x
centersSumY = centersSumY + point.y
centersSumZ = centersSumZ + point.z
centerX = centersSumX/numberOfPoints
centerY = centersSumY/numberOfPoints
centerZ = centersSumZ/numberOfPoints
center = Point3D(float(centerX), float(centerY) , float(centerZ))
return center
While here you can find the code that I am trying to debug:
from classDatabase import Point3D, PointCloud3D
testPoint1 = Point3D(1.5, 0.2, 2.3)
testPoint2 = Point3D(3.5, 1.2, 5.3)
testPointCloud3D = PointCloud3D()
testPointCloud3D.addPoint(testPoint1)
testPointCloud3D.addPoint(testPoint2)
Finally a screenshot of the issue:

Methods with keywords from the instances's attributes

The perfect, but impossible, scenario would be:
class example(object):
def __init__(self,x,y):
self.x = x
self.y = y
def foo(self, x = self.x, y = self.y):
return x + y
It doesn't work because self isn't defined. I have done lots of research, looked on decorators, descriptors, metaclasses, almost everything. The solution may be the most obvious and known to all, but I couldn't find it. I could manage two workarounds, as follows:
def prep(argslist, argsprovided, attributes):
argsout = []
for name in argslist:
if name in argsprovided:
argsout.append(argsprovided[name])
else:
argsout.append(getattr(attributes,name))
return argsout
class example(object):
# I can create a default instance or a custom one
def __init__(self,x = 1,y = 1,z = 1,w = 1):
self.x = x
self.y = y
self.z = z
self.w = w
# I can wrap a function to use the self argument
def wrapper(self):
def foo(x = self.x, y = self.y, z = self.z, w = self.w):
return x + y + z + w
return foo
# I can wrap 'joo' alongside with foo, and make 'wrapper' return a list
def joo(self, **kwargs):
[x,y,z,w] = prep(['x','y','z','w'],kwargs,self)
return x + y + z + 2*w
# I can use my custom 'prep' function to to the job
def foo(self, **kwargs):
[x,y,z,w] = prep(['x','y','z','w'],kwargs,self)
return x + y + z + w
# Creates a default instance and a custom one
c = example()
d = example(2,2,2,2)
# I can use 'foo' with the instance's default values with both wrapping and 'prepping'
print(c.wrapper()())
print(d.wrapper()())
print(c.foo())
print(d.foo())
# I can use 'foo' with a mix of default values and provided values with both wrapping and 'prepping'
print(c.wrapper()(1,2,3))
print(d.wrapper()(1,2,3))
print(c.foo(y = 3,z = 4,w = 5))
print(d.foo(y = 3,z = 4,w = 5))
The code prints out:
4
8
4
8
7
8
13
14
I have a huge class with lots of functions, every one needs the behavior of 'foo'. My prep solution is too time consuming. After profiling the code, I figured it spent 12 seconds inside prep only. What is a clever and less time consuming way of doing this? I'm completely lost.
I'm not sure it will help but how about using None as a default value and use a clause to determine the value. For example:
def foo(self, x=None, y=None):
real_x = x if x != None else self.x
real_y = y if y != None else self.y
return real_x + real_y
I found six ways of doing what I wanted. After profiling the code, the result was:
afoo foo noo1 noo2 wrap1 wrap2
6.730 28.507 3.98 4.097 10.256 3.468
6.407 28.659 4.096 3.924 9.783 3.529
6.277 28.450 3.946 3.889 10.265 3.685
6.531 30.287 3.964 4.149 10.077 3.674
As you will see ahead, noo1, noo2 and wap2 are quite similar on code. The conventional method afoo is not that efficient. My custom method foo is terrible and wrap1 was just tested for the sake of completeness.
afoo.py
The drawback is that you need an extra line for each function argument.
class example(object):
# I can create a default class or a custom one
def __init__(self,x = 1,y = 1,z = 1,w = 1):
self.x = x
self.y = y
self.z = z
self.w = w
def afoo(self, x = None, y = None, z = None, w = None):
x = x if x != None else self.x
y = y if y != None else self.y
z = z if z != None else self.z
w = w if w != None else self.w
return x + y + z + w
c = example(2,2,2,2)
for i in range(0, 10000000):
c.afoo(1,2,3,4)
foo.py
This one is the slower method.
def prep(argslist, argsprovided, attributes):
argsout = []
for name in argslist:
if name in argsprovided:
argsout.append(argsprovided[name])
else:
argsout.append(getattr(attributes,name))
return argsout
class example(object):
# I can create a default class or a custom one
def __init__(self,x = 1,y = 1,z = 1,w = 1):
self.x = x
self.y = y
self.z = z
self.w = w
def foo(self, **kwargs):
[x,y,z,w] = prep(['x','y','z','w'],kwargs,self)
return x + y + z + w
c = example(2,2,2,2)
for i in range(0, 10000000):
c.foo(x = 1,y = 2,z = 3,w = 4)
wrapper1.py
By far less efficient than wrapper2.py.
class example(object):
# I can create a default class or a custom one
def __init__(self,x = 1,y = 1,z = 1,w = 1):
self.x = x
self.y = y
self.z = z
self.w = w
def wrapper(self):
def foo(x = self.x, y = self.y, z = self.z, w = self.w):
return x + y + z + w
return foo
c = example(2,2,2,2)
for i in range(0, 10000000):
c.wrapper()(1,2,3,4)
wrapper2.py
class example(object):
# I can create a default class or a custom one
def __init__(self,x = 1,y = 1,z = 1,w = 1):
self.x = x
self.y = y
self.z = z
self.w = w
def wrapper(self):
def foo(x = self.x, y = self.y, z = self.z, w = self.w):
return x + y + z + w
return foo
c = example(2,2,2,2)
k = c.wrapper()
for i in range(0, 10000000):
k(1,2,3,4)
noo1.py
class example(object):
# I can create a default class or a custom one
def __init__(self,U,x = 1,y = 1,z = 1,w = 1):
self.x = x
self.y = y
self.z = z
self.w = w
def noo(x = self.x, y = self.y, z = self.z, w = self.w):
return x + y + z + w
self.noo = noo
c = example(2,2,2,2)
for i in range(0, 10000000):
c.noo(1,2,3,4)
noo2.py
class example(object):
# I can create a default class or a custom one
def __init__(self,x = 1,y = 1,z = 1,w = 1):
self.x = x
self.y = y
self.z = z
self.w = w
def __call__(self):
def noo(x = self.x, y = self.y, z = self.z, w = self.w):
return x + y + z + w
self.noo = noo
c = example(2,2,2,2)
c()
for i in range(0, 10000000):
c.noo(1,2,3,4)
When testing these codes I included the prep function in all of them, just to be shure they had the same basic structure, and thus the time difference would be from the loops.

How to assign target in custom threads?

from threading import *
from random import *
class Ant(Thread):
def __init__(self, x, y):
Thread.__init__(self)
self.x = x
self.y = y
def move(self, x, y):
self.x = x
self.y = y
class Ant_farm():
def __init__(self, x, y):
self.x = x
self. y = y
self.matrix = matrix(x, y)
self.condition = Condition()
def move(self, ant):
with self.condition:
x1, y1 = next_post(ant)
while self.matrix[x1][y1]:
self.condition.wait()
self.matrix[ant.x][ant.y] = False
ant.move(x1, y1)
self.matrix[ant.x][ant.y] = True
self.condition.notify_all()
def next_pos(self, ant):
while True:
choice = {0: (ant.x, ant.y - 1),
1: (ant.x + 1, ant.y),
2: (ant.x, ant.y + 1),
3: (ant.x - 1, ant.y)}
x1, y1 = choice[randrange(0, 4)]
try:
self.matrix[x1][y1]
except IndexError:
pass
else:
return x1, y1
def __str__(self):
res = '\n'
for i in range(self.x):
aux = ''
for j in range(self.y):
aux += str(self.matrix[i][j]) + ' '
aux += '\n'
res += aux
return res
def matrix(x, y):
return [[False for j in range(y)] for i in range(x)]
if __name__ == '__main__':
ant_farm = Ant_farm(7, 7)
for i in range(4):
# t = Ant(target = ant_farm.move)
pass
I want to run move function inside Ant threads. I tried to do:
t = Ant(target = ant_farm.move)
But the interpreter says this:
TypeError: init() got an unexpected keyword argument 'target'
I understand the error, but I don't know how to do what I said.

Overriding the plus operator for a user defined vector class in Python

I have written a class to work with three dimensional vectors as follows
class vector(object):
def __init__(self, x=None, y=None, z=None, angle=None):
if angle == None:
self.x, self.y, self.z = x, y, z
if angle != None:
if angle == "rad":
self.r, self.theta, self.phi = x, y, z
if angle == "deg":
self.r = x
self.theta = y * 2 * pi / 360.
self.phi = z * 2 * pi / 360.
self.x = self.r * sin(self.theta) * cos(self.phi)
self.y = self.r * sin(self.theta) * sin(self.phi)
self.z = self.r * cos(self.theta)
def write(self):
file.write("[" + str(self.x) + ",\t" + str(self.y) + ",\t" + str(self.z) + "]")
def write_sph(self):
file.write("[" + str(self.mag()) + ",\t" + str(self.gettheta()) + ",\t" + str(self.getphi()) + "]")
def getx(self):
return self.x
def gety(self):
return self.y
def getz(self):
return self.z
def setx(self, x):
self.x = x
def sety(self, y):
self.y = y
def setz(self, z):
self.z = z
def square(self):
return self.x*self.x + self.y*self.y + self.z*self.z
def mag(self):
return sqrt(self.square())
def gettheta(self):
return arccos(self.z / self.mag())
def getphi(self):
return arctan2(self.y, self.x) # sign depends on which quadrant the coordinates are in
def __add__(self, vector(other)):
v_sum = vector(other.gettx() + self.gettx(), other.getty() + self.getty(), other.getty() + self.getty())
return v_sum
In the last definition I am attempting to override the operator for addition. The definition works by calling a new vector named other and adding its x,y,z components to the corresponding components of self. When I run the code I'm told the syntax for the definition is invalid. How do I correctly define the vector argument for this overriding definition? Also what difference would changing the definition from def __ add __ to simply def add make? i.e what do the underscores denote?
You shouldn't have vector(other) in your parameter list - just say other. Also, you'll need to fix the typos in the add method:
def __add__(self, other):
v_sum = vector(other.getx() + self.getx(), other.gety() + self.gety(), other.getz() + self.getz())
return v_sum

Categories

Resources