在方法之外使用 super() 获取父 class 中的私有属性

Getting private attribute in parent class using super(), outside of a method

我有一个带有私有常量 _BAR = object() 的 class。

在子 class 中,在方法之外(无法访问 self),我想引用 _BAR

这是一个人为的例子:

class Foo:
    _BAR = object()

    def __init__(self, bar: object = _BAR):
        ...

class DFoo(Foo):
    """Child class where I want to access private class variable from parent."""

    def __init__(self, baz: object = super()._BAR):
        super().__init__(baz)

不幸的是,这不起作用。一个错误:RuntimeError: super(): no arguments

有没有办法在方法之外使用 super 来获取父 class 属性?


解决方法是使用 Foo._BAR,我想知道是否可以使用 super 来解决这个问题。

DFoo里面,你不能不引用Foo就引用Foo._BAR。 Python 变量在本地、封闭、全局和内置范围内搜索(按此顺序,这就是所谓的 LEGB 规则)并且 _BAR 不存在于其中任何一个。

让我们忽略一个明确的 Foo._BAR

此外,它被继承:DFoo._BAR 将首先在 DFoo 中查找,如果找不到,则在 Foo.

中查找

还有什么其他方法可以获取Foo引用? FooDFoo 的基数 class。我们可以利用这种关系吗?是和不是。在执行时是,在定义时否。

问题是在定义 DFoo 时,它还不存在。我们没有开始跟踪继承链的起点。这排除了 def method(self, ....): 行和 class 属性 _DBAR = _BAR.

中的间接引用 (DFoo -> Foo)

可以使用 class 装饰器来解决此限制。定义class然后修改它:

def deco(cls):
    cls._BAR = cls.__mro__[1]._BAR * 2  # __mro__[0] is the class itself
    return cls 

class Foo:
    _BAR = 10

@deco
class DFoo(Foo):
    pass

print(Foo._BAR, DFoo._BAR) # 10 20

使用 metaclass.

可以达到类似的效果

获取对 Foo 的引用的最后一个选项是在执行时。我们有对象 self,它的类型是 DFoo,它的父类型是 Foo,并且存在 _BAR。众所周知的 super() 是获取父级的快捷方式。

为简单起见,我假设只有一个碱基 class。如果有多个基 classes,super() returns 只有其中一个。例子 class 装饰器做同样的事情。要了解如何将多个碱基分类为一个序列,请参阅 MRO 的工作原理(方法解析顺序)。

我最后的想法是,我想不出一个需要问题中的访问权限的用例。

简答:你不能!

我不会详细介绍 "super" 但让我们看看如何调用 super:

1- 没有参数,正如文档所说:

The zero argument form only works inside a class definition, as the compiler fills in the necessary details to correctly retrieve the class being defined, as well as accessing the current instance for ordinary methods.

(function/methods 的主体 不会 执行,除非它被调用,所以如果 DFoo 还不存在也没问题)

2- 有两个参数,上面提到的必要细节是什么?一个“类型”和一个“实例”:

我们不能在此处传递 DFoo 的“实例”和“类型”。第一个是因为它不在方法内部,所以我们无权访问 instance(self)。第二个是 DFoo 本身。当 DFoo class 的主体被执行时,还没有对 DFoo 的引用,它还不存在。 class 的主体在作为字典的名称空间内执行。 之后,使用填充的字典创建了类型 type 的新实例,此处命名为 DFoo,并将其添加到全局命名空间。这就是 class 关键字在简单形式中的大致作用。

3-另外两个参数都是类型:

If the second argument is a type, issubclass(type2, type) must be true

与上面提到的访问 DFoo.

的原因相同

4- 还有另一种调用 super 的形式,参数是一个单一的“类型”:

If the second argument is omitted, the super object returned is unbound.

与上述访问 DFoo 类型的原因相同,没有任何变化。刚刚添加记录。这些是我们如何调用 super.

的方法