установка свойства в __init__ - PullRequest
0 голосов
/ 26 сентября 2018

Я хочу создать дочерний класс B из A и использовать __init__ из A, поскольку он идентичен одному атрибуту / свойству.

Следующий код показывает, что я хотел бы сделать

class A:
    def __init__(self):
        self.a = 1
        self.b = 1
        self.c = 1

class B(A):
    def __init__(self):
        super().__init__()  # because I want 'a' and 'b', (but not 'c')

    @property
    def c(self):
        return 2

B()

Traceback:

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-9-95c544214e48> in <module>()
     13         return 2
     14 
---> 15 B()

<ipython-input-9-95c544214e48> in __init__(self)
      7 class B(A):
      8     def __init__(self):
----> 9         super().__init__()  # because I want 'a' and 'b', (but not 'c')
     10 
     11     @property

<ipython-input-9-95c544214e48> in __init__(self)
      3         self.a = 1
      4         self.b = 1
----> 5         self.c = 1
      6 
      7 class B(A):

AttributeError: can't set attribute

Я думал, что смогу решить эту проблему, выполнив

class B(A):
    def __init__(self):
        super().__init__()  # because I want 'a' and 'b', (but not 'c')
        self.c = property(lambda s: 2)

Однако при вызове:

>>> B().c
<property at 0x116f5d7c8>

свойство не оценивается.

Как правильно сделать это, не копируя вручную __init__ из A?

1 Ответ

0 голосов
/ 26 сентября 2018

Один из способов исправить это - также превратить c в свойство в A;свойство просто возвращает (приватный) член self._c:

class A:
    def __init__(self):
        self.a = 1
        self.b = 1
        self._c = 1

    @property
    def c(self):
        return self._c

class B(A):
    def __init__(self):
        super().__init__()  # because I want 'a' and 'b', (but not 'c')
        self._c = 2

    # is already inherited from A
    # @property
    # def c(self):
    #     return self._c

a = A()
b = B()
print(a.c)  # 1
print(b.c)  # 2

, если вы не можете изменить A (и при условии, что целью вашей собственности является заставить c прочитать-только), это вариант: c.setter вызовет ошибку, если self._c не None:

class A:
    def __init__(self):
        self.a = 1
        self.b = 1
        self.c = 1

class B(A):
    def __init__(self):
        self._c = None
        super().__init__()  # the setter for c will work as self._c = None
        self._c = 2         # now we set c to the new value 
                            # (bypassing the setter)

    @property
    def c(self):
        return self._c

    @c.setter
    def c(self, value):
        if self._c is not None:
            raise AttributeError
        self._c = value
...