【问题标题】:setting a property in __init__在 __init__ 中设置属性
【发布时间】:2019-03-02 09:10:05
【问题描述】:

我想从A 创建一个子类B 并使用A 中的__init__,因为它最多有一个属性/属性相同。

以下代码显示了我想做的事情

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()

追溯:

---------------------------------------------------------------------------
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>

不评估该属性。

如何在不从A 手动复制__init__ 的情况下正确执行此操作?

【问题讨论】:

  • 在我看来,B 根本不应该真正继承自 A。一个通用的超类可能是合适的。
  • 这里有点难以理解你的用例,因为你已经匿名了太多。你真的需要 B.c 成为一个财产,还是那是一个例证?调用 super() 后不能简单地设置 self.c = 2 有什么原因吗?
  • 用例是(仍然比我想要的更简单)A 的许多方法使用c,但是B 添加了一些功能并使c 成为@ 987654339@ 而不是number,则属性c 取该list 的平均值。

标签: python class properties attributes


【解决方案1】:

一种补救方法是将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

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2011-04-25
  • 2015-11-29
  • 2018-02-23
  • 2011-06-16
  • 2017-12-14
  • 2019-04-22
  • 2016-01-12
相关资源
最近更新 更多