在方法之外使用 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
引用? Foo
是 DFoo
的基数 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
.
的方法
我有一个带有私有常量 _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
引用? Foo
是 DFoo
的基数 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
.