【问题标题】:A class property does not make it to the instance of the inheriting class?一个类属性不让它成为继承类的实例?
【发布时间】:2022-01-10 23:27:32
【问题描述】:

我已经通过在元类中定义带有@property 装饰器的属性来定义类属性,正如SO answer 中所建议的那样。

由于在定义后我只能访问类定义(将从元类继承),因此我将在之后继承它,这要归功于上述 SO 答案中给出的技巧。

我希望定义的类属性在继承类及其实例中都可用。 但我没有成功在它的实例中拥有它。

那么,让我们回顾一下我当前的代码:

class TopLevel(type):
    """ TopLevel metaclass defining class properties. """
    @property
    def depth(cls) -> int:
        return cls._depth

class OtherClass:
    """ Class that will inherit from 'TopLevel' after it has been defined.
        Dummy implementation."""
    def __init__(self, var):
        self.var = var


# Making 'Otherclass' inheriting from metaclass 'TopLevel' to have available
# as class properties 'depth'.
# As per https://stackoverflow.com/a/5121381/4442753
OtherClass = TopLevel(OtherClass.__name__,
                      OtherClass.__bases__,
                      dict(OtherClass.__dict__))
# Set a value to '_depth'
OtherClass._depth = 3

# Check OtherClass has 'depth' class property
OtherClass.depth
Out[6]: 3

# Instanciate OtherClass: instance has no 'depth' attribute?
otherclass = OtherClass(4)
otherclass.depth
Traceback (most recent call last):

  File "/tmp/ipykernel_748533/2343605532.py", line 1, in <module>
    otherclass.depth

AttributeError: 'OtherClass' object has no attribute 'depth'

这可以实现吗?

编辑

代码 sn-p 说明了我对 @martineau 第一条评论的回答:

class A:
    a=2

class B(A):
    def __init__(self,var):
        self.var = var
        
b = B(42)

b.a
Out[26]: 2

b.var
Out[27]: 42

【问题讨论】:

  • 为什么您首先希望类属性可用于该类的实例 - 无论该属性是否被继承?
  • 嗨,马蒂诺。我想我对@property 的作用还不清楚。我正在想象无论它做什么,结果都会作为继承类中的类属性保存。实例化一个类时,您会发现类属性进入其实例,这是“正常”行为。我在初始帖子中给出了一个代码 sn-p。在这段代码 sn-p 中,如果我将“保护”“b”作为类属性,我希望它在类实例中受到保护。下面的答案使这成为可能,它符合我的需要。
  • 您的更新令人困惑,因为 avar 被赋予相同的值。如果您将其更改为b = B(42),则生成的b.var 值不会令人惊讶地为42 — 这并不意味着aB 属性正在通过bB 的实例进行访问.
  • 对不起,martineau,我不明白你的评论。我根据您的评论进行了更改以减少混乱,它仍然显示了我认为是您最初问题的答案:因为将“类属性”的东西分开,从类 B 继承的类 A 的实例保持类B 属性。这就是为什么我期待这个 B 类属性,如果它被更改为属性,则保留在 A 的实例中。我期待“正常的 python 行为”保留,该属性是否是 B 中的属性。
  • 好吧,这更有意义。

标签: python inheritance


【解决方案1】:

这是一个解决方案:

class TopLevel(type):
    """ TopLevel metaclass defining class properties. """
    @property
    def depth(cls) -> int:
        return cls._depth

class OtherClass:
    """ Class that will inherit from 'TopLevel' after it has been defined.
        Dummy implementation."""
    def __init__(self, var):
        self.var = var

# explicitely add property to OtherClass.__dict__
d = dict(OtherClass.__dict__)
d.update({"depth": TopLevel.depth})

OtherClass = TopLevel(OtherClass.__name__,
                      OtherClass.__bases__,
                      d)

OtherClass._depth = 3

otherclass = OtherClass(4)
print(otherclass.depth)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-08
    • 1970-01-01
    • 2019-02-07
    • 1970-01-01
    • 2023-03-09
    • 2012-02-06
    • 1970-01-01
    相关资源
    最近更新 更多