Hey my task is to create a parentclass Shape and pass the functions on to the different shapes. Since a Circlearea calculation takes different parameters I am trying to overwrite the function. It throws following warning: "Signature of method 'Circel.get_area()' does not match Signature in the base method in Shape". Is that possible at all? How would I have to do it? Should it work anyway later on?
class Shape(ABC):
#abstractmethod
def get_area(self, x_l, y_l):
pass
def move(self, newx, newy):
pass
class Circle(Shape):
def __init__(self, rad, x_pos, y_pos):
self.rad = rad
self.pos = (x_pos, y_pos)
self.area = self.get_area(self, self.rad)
def get_area(self, rad):
return(self.rad*self.rad*2*m.pi)
Related
The following example was given in my python book:
class Rectangle:
def __init__(self, length, width):
self.length = length
self.width = width
def area(self):
return (self.width * self.length)
class Square(Rectangle):
def __init__(self, side_length):
super().__init__(side_length, side_length)
shape = Square(4)
print(shape.area())
The programme prints 16.
From what I understand, super() looks for the init method within the parent class (which is Rectangle). It finds it and makes it use the side_length attribute for length and width. Then, area() is called with the variable side_length. Is this how the code is working or have I misunderstood it?
Suppose I have a parent class and multiple child classes, which extend the parent class by including more specific information about the ideas they represent. For example:
class Shape:
def __init__(self, center):
self.center = center
class Square(Shape):
def __init__(self, center, side_length):
super().__init__(self, center)
self.side_length = side_length
self.area = side_length ** 2
class Circle(Shape):
def __init__(self, center, radius):
super().__init__(self, center)
self.radius = radius
self.area = 3.14 * (radius ** 2)
Suppose I want to implement a method such as translate(new_center) in the parent class, which would return a new object with a different center location than the original object. Because all child classes should behave the same way (i.e. the attribute self.center should change), it makes sense to implement translate() as a method of the parent class Shape.
If I want to return a new object of type Shape every time translate() is called, we can simply define translate() as a method of Shape like so:
def translate(self, new_center):
return Shape(new_center)
However, if any child class instances call this method, the result will be of type Shape, and thus any additional state information contained by the original instance, such as side_length and area for a Square, will be lost. Additionally, translate() cannot be defined as
def translate(self, new_center):
return self.__class__(new_center)
because the constructors for each of the child classes require additional arguments that the parent class constructor doesn't. How can I implement this without having to override the parent method in each of the child classes (avoiding which was the entire point of defining the parent method)?
You could copy the object and modify the copy:
import copy
class Shape():
def __init__(self, center):
self.center = center
def translate(self, new_center):
new_shape = copy.copy(self) # Replace with deepcopy if needed
new_shape.center = new_center
...
class Cylinder(object):
self.pi = 3.14
def __init__(self,height=1,radius=1):
self.height = height
self.radius = radius
def volume(self):
return self.pi * self.radius**2 * self.height
def surface_area(self):
pass
Remove self from the second line. self is used only inside class methods to access class instance. But class attributes declared on class-level apply not to single class instance, but to class itself and all its instances: so they do not require self.
Is it possible to inherit a class and use its init function without declaring all parameters again in the child class?
I have a class with lots of parameters, but I don't want to use a list (**args). I wouldn't see my actual parameters:
class Table(object):
def __init_(self, name, height ...):
self.name = name
self.height = height
class RoundTable(Table):
def __init__(self, radius):
self.radius = radius
table = RoundTable(name = "Placeholder",
height = 10,
radius = 20)
Use the super class before assigning specfic args
def __init__(self,radius,*args,**kwargs):
super().__init__(*args,**kwargs)
self.radius = radius
Edit : I'm assuming you mean class and not a function
I want an attribute of a child class to have a different name than the same attribute of its parent class even though it means the same thing. For example, a parent class is Shape with attribute "height" and child class Circle with similar arttribute "Diameter". Below is a simplification of what I current have but I want the Circle class to use "diameter" instead of "height". What is the best way to handle this?
NOTE: I will inherit from Circle in another class that also needs to use "diameter" instead of "height". Thank you!
class Shape():
def __init__(self, shape, bar_args, height):
self.shape = shape
self.height = height
etc.
class Circle(Shape):
def __init__(self, height, foo_args, shape='circle'):
Shape.__init__(self, shape, height)
self.height = height
etc.
You could define a property which accesses the original attribute on read and write access:
class Circle(Shape):
def __init__(self, height, foo_args, shape='circle'):
Shape.__init__(self, shape, height) # assigns the attributes there
# other assignments
#property
def diameter(self):
"""The diameter property maps everything to the height attribute."""
return self.height
#diameter.setter
def diameter(self, new_value):
self.height = new_value
# deleter is not needed, as we don't want to delete this.
If you want this behaviour very often and you find property handling with setter and getter too unhandy, you can go a step higher and build your own descriptor class:
class AttrMap(object):
def __init__(self, name):
self.name = name
def __get__(self, obj, typ):
# Read access to obj's attribute.
if obj is None:
# access to class -> return descriptor object.
return self
return getattr(obj, self.name)
def __set__(self, obj, value):
return setattr(obj, self.name, value)
def __delete__(self, obj):
return delattr(obj, self.name)
With this, you can then do
class Circle(Shape):
diameter = AttrMap('height')
def __init__(self, height, foo_args, shape='circle'):
Shape.__init__(self, shape, height) # assigns the attributes there
# other assignments
and the diameter descriptor will redirect all accesses to it to the named attribute (here: height).