Check if variable is defined in the superclass or subclass - python

This is just academic. Consider the following example:
class Shape():
def __init__(self, x, y):
self.x = x
self.y = y
def position(self):
return self.x, self.y
class Rectangle(Shape):
def __init__(self, x, y, height, width):
#super().__init__(x, y) # OK
self.x = x # not OK!
self.y = y # not OK!
self.height = height
self.width = width
r1 = Rectangle(1, 2, 3, 4)
If I asked someone to implement the class Rectangle, and they implemented with the "not OK" statements (instead of the with the "OK" statement as they should), then r1.x would be an attribute of Rectangle instead of Shape. Is there a way I can check if r1.x is a member of the Rectangle class or of the Shape class? Essentially, I want to make sure the initialization of the super class is being run, and no unnecessary new attributes are being created.

Related

Too many posit. arguments and no value for argument python OOP

Hi Im just starting to learn OOP and I use python to do so. Recently I ve been trying to code a game. I ve declared class Character that should be general and from that class my other classes will inherit. Now Im trying to create a class Player, I want to inherit everything but 1 variable. Here is a code:
class Character:
def __init__(self, x, y, width, height):
self.width = width
self.height = width
self.x = x
self.y = y
self.vel = 3
self.right = False
self.left = False
self.walk_count = 0
self.is_jump = False
self.jump_count = 10
self.standing = True
class Player(Character):
def __init__(self, x, y, width, height, right, left, walk_count, is_jump, jump_count, standing):
super().__init__(x, y, width, height, right, left, walk_count, is_jump, jump_count, standing)
self.vel = 5
in super() I keep getting pylint error:
Too many positional arguments for method call.
But I think it lets me run it even with it.
Also I want to put in only self.x, self.y, self.width and self.height when initializing, should I declare these values in class Player or let it be in class Character?
Then here I try to create an instance of class Player:
man = Player(200,410,64,64)
And I got errors missing value for argument right, left, walk_count,
is_jump, jump_count, standing
I tought that if i set values for them in class Character that I dont need to put values in when creating instance, because I want to set them to default values at the creation and then I will change them if I need it.
Later I will add class Enemy that will inherit most of the parameters from class Character also.
Then, you must call the super method with the signature (number of parameters) desired.
Change
def __init__(self, x, y, width, height, right, left, walk_count, is_jump, jump_count, standing):
super().__init__(x, y, width, height, right, left, walk_count, is_jump, jump_count, standing)
self.vel = 5
to
def __init__(self, x, y, width, height):
super().__init__(x, y, width, height)
self.vel = 5
Or, if you prefer, change Character's __init__ to match the Player's super call, and change:
class Character:
def __init__(self, x, y, width, height):
to
class Character:
def __init__(self, x, y, width, height, right, left, walk_count, is_jump, jump_count, standing):
and leave the super call as is.
The best approach is to only pass what is needed. If the only needed values to parameterize your Character object are x,y,height,weight, then you should only pass them - the remaining will be set automatically (you don't need to give them as input, since they will be discarded).
So, the correct approach is the first I mentioned.

Calling a method from parent class that has a different name in the subclass

Having the following code:
class Point:
'class that represents a point in the plane'
def __init__(self, xcoord=0, ycoord=0):
''' (Point,number, number) -> None
initialize point coordinates to (xcoord, ycoord)'''
self.x = xcoord
self.y = ycoord
def setx(self, xcoord):
''' (Point,number)->None
Sets x coordinate of point to xcoord'''
self.x = xcoord
def sety(self, ycoord):
''' (Point,number)->None
Sets y coordinate of point to ycoord'''
self.y = ycoord
def get(self):
'''(Point)->tuple
Returns a tuple with x and y coordinates of the point'''
return (self.x, self.y)
def move(self, dx, dy):
'''(Point,number,number)->None
changes the x and y coordinates by dx and dy'''
self.x += dx
self.y += dy
def __repr__(self):
'''(Point)->str
Returns canonical string representation Point(x, y)'''
return 'Point('+str(self.x)+','+str(self.y)+')'
class Rectangle(Point):
def __init__(self,bottom_left,top_right,color):
self.get = bottom_left
self.get = top_right
self.color = color
def get_bottom_left(self,bottom_left):
print ()
r1 = Rectangle(Point(0,0), Point(1,1), "red")
r1.get_bottom_left()
I want to be able to print "Point(0,0)" by calling self__rep__(self) from class Point from the method get_bottom_left, but I just have no idea how. I know how to use inheritance if the functions have the same name, but in this case I am stuck and it is a requirement for the child function to have the method names it has. If it looks that I am just looking for the answer, I would like the response to just explain me a similar case of this application please!
When I do the following:
class Rectangle(Point):
def __init__(self,bottom_left,top_right,color):
self.get = bottom_left
self.get = top_right
self.color = color
def get_bottom_left(self,bottom_left):
print (self.bottom_left)
I get: get_bottom_left() missing 1 required positional argument: 'bottom_left'
As mentioned in the comment, Rectangle should contain Point instances and not inherit Point. If you change Rectangle class as shown below, you'll see the expected result:
class Rectangle():
def __init__(self, bottom_left, top_right, color):
self.bottom_left = bottom_left
self.top_right = top_right
self.color = color
def get_bottom_left(self):
print self.bottom_left

Comparing variables within classes in python

I'm trying to write a method(it) that compares the size (area) of the rectangle with the area of another rectangle passed as a parameter:
class Rectangle:
def __init__(self, x, y):
self.width = x
self.height = y
def area(self):
a = self.width * self.height
return a
def __it__(self,second):
return self.area < second.area
But I keep getting error:
TypeError: unorderable types: Rectangle() < Rectangle()
I'm not to sure how to fix this problem
You had a typo. It's __lt__, not __it__, and you need to call the area() as a function unless you set that as a property.
Fixing all that...
>>> class Rectangle:
... def __init__(self, x, y):
... self.width = x
... self.height = y
... def area(self):
... a = self.width * self.height
... return a
... def __lt__(self,second):
... return self.area() < second.area()
...
>>> Rectangle(1,3) > Rectangle(4,5)
False
Area is a method, you're using it as though it's a variable. Adding parens should fix it (and if you're trying to do less than, it should be __lt__):
def __lt__(self, second):
return self.area() < second.area()

Learning class in python but having issue that probably is simple

I have simple code that creates a rectangle
class Point:
def __init__(self, x=0, y=0):
self.x = x
self.y = y
class Rectangle:
def __init__(self, posn, w, h):
self.corner = posn
self.width = w
self.height = h
def __str__(self):
return "({0},{1},{2})".format(self.corner, self.width, self.height)
box = Rectangle(Point(0, 0), 100, 200)
print("box: ", box)
The output of this code is
('box: ', <__main__.Rectangle instance at 0x0000000002368108>)
I expect the output to be
box: ((0, 0), 100, 200)
Can someone please help?
You don't define a __repr__() on your Rectangle class. Printing a tuple (as you are doing) uses the repr() of the class, not the str(). You also need a __str__() on your Point class.
You need to define __repr__ in both the Classes, like this
class Point(object):
def __init__(self, x=0, y=0):
self.x = x
self.y = y
def __repr__(self):
return "({}, {})".format(self.x, self.y)
class Rectangle(object):
def __init__(self, posn, w, h):
self.corner = posn
self.width = w
self.height = h
def __repr__(self):
return "({0},{1},{2})".format(self.corner, self.width, self.height)
print "box: ", box
# box: ((0, 0),100,200)
It seems like you're using Python 2.x: In Python 2.x, print is statement, not a function.
By putting (...), you're printing str(("box:", box)). (A tuple containing a string and Rectangle object)
Remove parentheses, and define Point.__str__ to get what you expected.
class Point:
def __init__(self, x=0, y=0):
self.x = x
self.y = y
def __str__(self):
return str((self.x, self.y))
# OR return '({0.x}, {0.y})'.format(self)
class Rectangle:
def __init__(self, posn, w, h):
self.corner = posn
self.width = w
self.height = h
def __str__(self):
return "({0},{1},{2})".format(self.corner, self.width, self.height)
box = Rectangle(Point(0, 0), 100, 200)
print("box: ", box) # This prints a tuple: `str(("box: ", box))`
print "box: ", box # This prints `box: ` and `str(box)`.
output:
('box: ', <__main__.Rectangle instance at 0x00000000027BC888>)
box: ((0, 0),100,200)

Inheritance error with Python

I have the following code.py file:
class Shape:
def __init__(self, x, y):
self.x = x
self.y = y
def move(self, delta_x, delta_y):
self.x += delta_x
self.y += delta_y
class Square(Shape):
def __init__(self, side=1, x=0, y=0):
super().__init__(x, y)
self.side = side
class Circle(Shape):
def __init__(self, rad=1, x=0, y=0):
super().__init__(x, y)
self.radius = rad
I'm running the code in the Python interpreter like this:
>>> import code
>>> c = code.Circle(1)
I'm getting this error:
Traceback (most recent call last):<br>
...<br>
File "code.py", line 18, in __init__<br>
super().__init__(x, y)<br>
TypeError: super() takes at least 1 argument (0 given)<br>
I don't understand why I'm getting this error. I'm specifying a rad value of 1 and I would assume that since I didn't specify x and y values, Circle should be using the default values of x=0 and y=0 and passing them to Shape via the super() function. What am I missing?
BTW, I'm using Python 2.7.1.
Thanks.
super requires an argument and this is exactly what the error message is saying. In your case you need to use super(Circle, self) and super(Square, self).
For the gory details you can see this SO question or you can just check the official documentation.
Note that unless you want to do funny things the code can be simplified in
Shape.__init__(self, x, y)
in both cases. Until you understand super and why it can be useful I would suggest to simply stay away from it. You can live an happy life as a productive Python programmer without touching that.
Use super(Shape, self) instead, you can help(super) in python.
Finally fixed it. :D Searching through python docs and old Stackoverflow posts for the win.
class Shape(object):
def __init__(self, x, y):
self.x = x
self.y = y
def move(self, delta_x, delta_y):
self.x += delta_x
self.y += delta_y
class Square(Shape):
def __init__(self, side=1, x=0, y=0):
super(Square,self).__init__(x, y)
self.side = side
class Circle(Shape):
def __init__(self, rad=1, x=0, y=0):
super(Circle,self).__init__(x, y)
self.radius = rad
c = Circle(5)
This works. You need to use new style classes by making the top parent (Shape) inherit from object.
References:
http://docs.python.org/reference/datamodel.html#newstyle
Chain-calling parent constructors in python
Here's some code that does what you need, you also need to be using the "new style class" meaning the base type needs to inherit from object:
class Shape(object):
def __init__(self, x, y):
self.x = x
self.y = y
def move(self, delta_x, delta_y):
self.x += delta_x
self.y += delta_y
class Square(Shape):
def __init__(self, side=1, x=0, y=0):
super().__init__(x, y)
self.side = side
class Circle(Shape):
def __init__(self, rad=1, x=0, y=0):
super(Circle, self).__init__(x, y)
self.radius = rad
P.S. I only fixed Circle and left Square for you to fix.

Categories