Inheritance error with Python - 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.

Related

Check if variable is defined in the superclass or subclass

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.

Python OOP - Soccer Simulation

I'm new to OOP. I'd like to simulate a soccer match. How do I access Play instance variables in the Player/Offender/Defender classes? If another structure is better, please help.
class Player:
def __init__(self, x, y):
self.x = x
self.y = y
def move_to(self, x, y):
self.x = (self.x + x) / 2
self.y = (self.y + y) / 2
## Loop through Play.Players to find nearest. How do I access Play.Players?
def nearest(self):
return nearest
class Offender(Player):
def __init__(self, x, y):
super().__init__(x, y)
# Move to ball.
def strategy():
ball_x = Play.ball_x # how do I access Play.ball_x
ball_y = Play.ball_y # how do I access Play.ball_y
self.move_to(ball_x, ball_y)
class Defender(Player):
def __init__(self, x, y):
super().__init__(x, y)
# Move to nearest player
def strategy(self):
nearest = self.nearest()
self.move_to(nearest)
class Play:
def __init__(self, offense_players, defense_players, ball_x, ball_y):
self.offense = [Offender(player) for player in offense_players]
self.defense = [Defender(player) for player in defense_players]
self.players = self.offense + self.defense
self.ball_x = ball_x
self.ball_y = ball_y
def simulate(self):
while True:
for player in self.players:
player.strategy()
if __name__ == "__main__":
Play().simulate()
Instead of having Offender and Defender classes, I have one for each position, i.e. Striker(Player), Midfielder(Player), Goalie(Player), etc. which is why I'd like to store their respective strategy in their class and not in the Play class.
Not sure how much this will be helpful for you, as the implementation is in C++
You can checkout my implementation for a similar problem statement https://github.com/rimpo/footballcpp
For understanding the arcade game framework implementation for which the above bot was written, checkout http://richard-shepherd.github.io/coding-world-cup/index.html
I just elaborate the idea from the comment of martineau: We just pass the Play instance as argument to the relevant methods of Player. I also wrote out a very first draft for the nearest() method, but you might want to improve its logic. I was just drafting this to demonstrate how you could solve your OOP design problem.
import typing
class Player:
def __init__(self, x: float, y: float):
self.x = x
self.y = y
def move_to(self, x: float, y: float) -> None:
self.x = (self.x + x) / 2
self.y = (self.y + y) / 2
def nearest(self, play: "Play") -> "Player":
# This must yet be adapted to handle the edge case of two players
# having equal distance to the current player. You didn't specify the
# desired output for that case, hence I just ignored that scenario for now.
return min([
p for p in play.players
if p.x != self.x or p.y != self.y, # this is to
# exclude the player itself.
# This is a buggy logic, because it relies on an assumption that is not
# validated in the code (the assumption that two different players never
# have identical coordinates). You might want to introduce a uniqe `id`
# instance variable to the Player class, to handle this identification in a
# clean way.
],
key=lambda p: (self.x - p.x)**2 + (self.y - p.y)**2
)
class Offender(Player):
def __init__(self, x: float, y: float):
super().__init__(x, y)
# Move to ball.
def strategy(self, play: "Play") -> None:
self.move_to(play.ball_x, play.ball_y)
class Defender(Player):
def __init__(self, x: float, y: float):
super().__init__(x, y)
# Move to nearest player
def strategy(self, play: "Play") -> None:
self.move_to(self.nearest(play=play)
class Play:
def __init__(
self,
offense_players: typing.List["Offender"],
defense_players: typing.List["Defender"],
ball_x: float,
ball_y: float,
):
self.offense = offense_players
self.defense = defense_players
self.players = self.offense + self.defense
self.ball_x = ball_x
self.ball_y = ball_y
def simulate(self) -> None:
while True: # this is still a bad condition, you might want to change this. However you didn't specify your desired logic, so I didn't change it.
for player in self.players:
player.strategy(self, play=self)
I would do the following:
keep track of game state in another (data) class:
class GameState:
def __init__(self, offense_players, defense_players, ball_x, ball_y):
self.offense = offense_players
self.defense = defense_players
self.players = self.offense + self.defense
self.ball_x = ball_x
self.ball_y = ball_y
You may even wish to use python3.7 dataclasses (and some other features) for this (although it is not at all necessary)
from dataclasses import dataclass
from typing import List
#dataclass
class GameState:
offense: List[Offender]
defense: List[Defender]
ball_x: float
ball_y: float
#property
def players(self):
return offense + defense
Players then take this state in their strategy and are expected to update their internal state (like position). nearest player is implemented by taking the minimum l2 distance between other players using the key argument to min that takes a function of another player, p which is written using lambda.
class Player:
def __init__(self, x, y):
self.x = x
self.y = y
def move_to(self, x, y, other_players):
self.x = (self.x + x) / 2
self.y = (self.y + y) / 2
def nearest(self):
return nearest
class Offender(Player):
def __init__(self, x, y):
super().__init__(x, y)
# Move to ball.
def strategy(self, game_state):
ball_x = game_sate.ball_x # how do I access Play.ball_x
ball_y = game_state.ball_y # how do I access Play.ball_y
self.move_to(ball_x, ball_y)
class Defender(Player):
def __init__(self, x, y):
super().__init__(x, y)
# Move to nearest player
def strategy(self, game_state):
# we assume you are moving to offensive players - which
# you will not be apart of
nearest = min(
game_state.offense
key=lambda p: (
(self.x - p.x) **2 + (self.y - p.y) ** 2
) ** (1/2) # take the l2 norm to find the "closest" player to you
)
self.move_to(nearest.x, nearest.y)
Then, play the game
class Play:
def __init__(self, game_state):
self.game_state = game_state
def simulate(self):
while True:
for player in self.game_state.players:
player.strategy(self.game_state)
if __name__ == "__main__":
Play(GameState(
[Offender(-1, 0), Offender(-1, -1), ...]
[Defender(1, 0), Offender(1, -1), ...]
)).simulate()
You could then implement some actual players
class TiernaDavidson(Defender):
def strategy(self, *args, **kwargs):
return better_strategy(*args, **kwargs)
You will have to ask her for the implementation of better_strategy ;)

Call class method from another class PYTHON

I am just trying to get a program that receives a point from one class, and then in another class, it uses that point as the center of the circle. I imagine this is simple but I don't know how to do it.
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
class Circle(Point):
def circle(self, center, radius):
Point.x = center
Point.y = center
self.radius = radius
You shouldn't subclass Point for your Circle class, it doesn't make much sense as they are two completely different things. Instead you can take a Point as the center of your circle and pass it into the Circle class in the init
class Circle(object):
def __init__(self, center: Point, radius):
self.center = center
self.radius = radius
The way you are doing it, with inheritance, is a bit confusing.
2 options are avalaible.
First : As mention by #Iain Shelvington, you could use the Point class as a member of your Circle class.
Second : If you really want to sub class it / inherit from the point in your circle, you have to super.init() it.
class Circle(Point):
def __init__(self, x, y, radius):
super().__init__(x, y) # which is the same as creating a self.x and y for Circle
self.radius = radius

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

Move points and check specific start value, using classes python

I need to be able to move points and check a specific point value. This is the code:
class Point(object):
def __init__(self, x, y):
self.x = x
self.y = y
def move(self)
#Here I want to move my points
Next class is a linestring. It must be able to handle x set of points
class LineString(Point):
def __init__(self, *points):
self.points = []
for point in points:
if not isinstance(point, Point):
point = Point(*point)
self.points.append(point)
def __getitem__(self):
#Here I want to inspect the value of the specific
# e.g. y value for the start point after it has been moved
I'm a bit unsure of how to get the __getitem__ to work and whether it's in the right position. Should it be under class Point? Could this be done in another way?
Edited code;
from numpy import sqrt
import math
class Point(object):
def __init__(self, x, y):
self.x = x
self.y = y
def dist(self, point):
return math.hypot(self.x - point.x, self.y - point.y)
def move(self, dx, dy):
self.x = self.x + dx
self.y = self.y + dy
class LineString(Point):
def __init__(self, *points):
self.points = []
for point in points:
if not isinstance(point, Point):
point = Point(*point)
self.points.append(point)
def length(self):
return sum(p1.dist(p2) for p1, p2 in zip(self.points[1:], self.points[:-1]))
def move (self, x, y):
for p in self.points:
p.move(x, y)
def __getitem__(self, key):
return self.points[key]
I think this is roughly what you want:
You don't seem to actually need a dictionary (for a line, I think a list makes more sense anyway). So the Line class is just a list of Points, and it provides a move_all_points function to translate them all. Because Line subclasses a list, you get all the standard behaviour of lists for free:
class Point(object):
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
return "<Point({},{})>".format(self.x, self.y)
def __str__(self):
return(repr(self))
def move(self, dx, dy):
"""Move the point by (dx, dy)."""
self.x += dx
self.y += dy
class Line(list):
"""A list of points that make up a line."""
def move_all_points(self, dx, dy):
for p in self:
p.move(dx, dy)
So then you can use them as follows:
>>> p1, p2, p3 = Point(0, 0), Point(5, 0), Point(10, 10)
>>> my_line = Line((p1, p2, ))
>>> print my_line
[<Point(0,0)>, <Point(5,0)>]
>>> my_line.append(p3)
>>> print my_line
[<Point(0,0)>, <Point(5,0)>, <Point(10,10)>]
>>> p4 = Point(100,100)
>>> my_line.move_all_points(1, 1)
>>> print my_line
[<Point(1,1)>, <Point(6,1)>, <Point(11,11)>]
>>> my_line.append(p4)
>>> print my_line
[<Point(1,1)>, <Point(6,1)>, <Point(11,11)>, <Point(100,100)>]

Categories