What is the correct way to overwrite variables in child classes that need to be computed in __init __ ()?

I study inheritance mechanisms in Python, and I want to make some variables that are automatically calculated inside the __init_ () child function, but the problem is that I want to create another class in which the variable will be overwritten. And I do not want these variables to be evaluated twice, once in the parent and then in the child. So is the example below?

class Shape(object):
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def getcenter(self):
        return self.x, self.y


class Square(Shape):
    def __init__(self, x, y, a):
        super().__init__(x,y)
        self.a = a
        self.perimeter = 4*a
        self.field = a*a


class Rectangle(Square):
    def __init__(self, x, y, a, b):
        super().__init__(x, y, a)
        self.perimeter = (2*a) + (2*b)
        self.field = a*b
+4
source share
3 answers

Well, ignoring yours above it would be better to have a rectangular Rectangle subclass, usually this type of logic will be moved to a new function, overridden by the subclass.

class Square:
   def __init__(self, a):
      self.a = a
      self.calculate_perimeter()

   def calculate_perimeter(self):
      self.perimeter = self.a * 4


class Rectangle(Square):
   def __init__(self, a, b):
      self.b = b
      super().__init__(a)

   # automatically called by the parent class
   def calculate_perimeter(self):
      self.perimeter = self.a * 2 + self.b * 2
+3

:

: " ?"

, ?

class Rectangle(Shape):
    def __init__(self, x, y, a, b):
        super(Rectangle, self).__init__(x, y)
        self.perimeter = (2 * a) + (2 * b)
        self.field = a * b


class Square(Rectangle):
    def __init__(self, x, y, a):
        super(Square, self).__init__(x, y, a, a)
        self.a = a

, , a=a b=a , .

- @property decorator " " ( )

class Shape(object):
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def getcenter(self):
        return self.x, self.y


class Square(Shape):
    def __init__(self, x, y, a):
        super(Square, self).__init__(x, y)
        self.a = a

    @property
    def perimeter(self):
        print("Perimeter of Square")
        return 4 * self.a

    @property
    def field(self):
        return self.a * self.a


class Rectangle(Square):
    def __init__(self, x, y, a, b):
        super(Rectangle, self).__init__(x, y, a)
        self.b = b

    @property
    def perimeter(self):
        print("Perimeter of Rectangle")
        return (2 * self.a) + (2 * self.b)

    @property
    def field(self):
        return self.a * self.b


if __name__ == "__main__":
    s = Square(1, 2, 3)
    r = Rectangle(5, 6, 7, 8)
    print ("Perimeter (square) %s" % s.perimeter)
    print ("Perimeter (rectangle) %s" % r.perimeter)

SO.

! , , (, , ) : -)

+2

perimeter field . , . .

, Square from Rectangle . , , Rectangle. , .

class Rectangle(Shape):
    def __init__(self, x, y, a, b):
        self.a = a
        self.b = b
        super().__init__(x, y)
    @property
    def perimeter(self):
        return (self.a + self.b) * 2


class Square(Rectangle):
    '''Just an alternate constructor for Rectangle'''
    def __init__(self, x, y, a):
        super().__init__(x, y, a, a) #b is same as a in a square.
    #everything else already works!

:

>>> my_square = Square(0, 0, 10)
>>> my_square.perimeter
40
>>> my_rect = Rectangle(0,0, 10, 5)
>>> my_rect.perimeter
30

, .

>>> my_square.perimeter = 10
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: can't set attribute

perimeter a b

#without properties you could get inconsistent values
>>> my_square.perimeter = 10
>>> print(my_square.perimeter, my_square.a, my_square.b)
10 10 10

, , , - .

class Circle(object):
    def __init__(self, radius):
        self.radius = radius

    @property
    def diameter(self):
        return self.radius * 2

    @diameter.setter
    def diameter(self, diam):
        self.radius = diam / 2

:

>>> my_circle = Circle(radius=5)
>>> my_circle.diameter
10
>>> my_circle.diameter = 40
>>> my_circle.radius
20
+2
source

Source: https://habr.com/ru/post/1658836/


All Articles