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?
Related
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)
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
...
This is my code:
class Rectangle(object):
def __init__(self, height, width):
self.height = height
self.width = width
def __str__(self):
return '{} x {} = {}'.format(self.height, self.width, self.area)
def area(self):
self.area=self.height*self.width
return self.area
def primarySchool(height, width):
return str(Rectangle(height, width))
For input height=7 and width=4 the output is
>>> primarySchool(7, 4):
7 x 4 = <bound method _runjcbjp.<locals>.Rectangle.area of
<__main__._runjcbjp.<locals>.Rectangle object at 0x2b482cd637f0>>
instead of 7 x 4 = 28.
How can I fix this?
In your Rectangle class, the area member is defined as a method.
As a consequence, print(self.area) will give you the representation of that method object, which is that <...> thing.
What you want is the result of the area method, not the method itself.
Therefore, you need to call the method, by writing parentheses after its name.
Your code should be:
return '{} x {} = {}'.format(self.height, self.width, self.area())
Additionnally, be careful not to reassign the same name in your method.
In your area method, you write:
self.area = self.height * self.width
As a consequence, after the first call to instance.area(), the area member will be overwritten, from a function to a number.
Subsequent calls would thus fail, with something like "Int object is not callable".
area is a method of your class, so you have to call it to get the return value (and not the method itself).
But given the fact that you assign to self.area inside the method it seems like you want it as "cached" property (accessible without calling it explicitly):
class Rectangle(object):
def __init__(self, height, width):
self.height = height
self.width = width
def __str__(self):
return '{} x {} = {}'.format(self.height, self.width, self.area)
#property
def area(self): # cached version
try:
return self._area
except AttributeError:
self._area=self.height*self.width
return self._area
def primarySchool(height, width):
return str(Rectangle(height, width))
primarySchool(7, 4)
# '7 x 4 = 28'
Or as uncached version:
class Rectangle(object):
def __init__(self, height, width):
self.height = height
self.width = width
def __str__(self):
return '{} x {} = {}'.format(self.height, self.width, self.area)
#property
def area(self):
return self.height*self.width
Or just calculate it in the __init__ and also set it as attribute:
class Rectangle(object):
def __init__(self, height, width):
self.height = height
self.width = width
self.area = height * width
def __str__(self):
return '{} x {} = {}'.format(self.height, self.width, self.area)
You're trying to have both a function and property called "area".
Why not simply:
def area(self):
return self.height*self.width
Call with:
self.area()
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