gpt4 book ai didi

python - 为什么父类(super class)属性在当前类的命名空间中不可用?

转载 作者:行者123 更新时间:2023-11-28 19:58:30 25 4
gpt4 key购买 nike

例子:

class A:
a = 1

class B(A):
b = 2
y = b # works fine
x = a # NameError: name 'a' is not defined
x = A.a # works fine

z = B()
z.a # works fine
B.a # works fine

为什么不允许x = a?在所有其他上下文中(通过实例访问,通过子类名称访问)它工作正常;但不知何故在类(class)本身内部,它不起作用。

鉴于这种行为,我似乎无法实现类层次结构,其中每个类都定义了一些额外的属性 - 因为如果不知道它们在层次结构中的确切定义位置,我将无法在子类中访问它们。

这是我尝试(未成功)做的事情:

class X:
accelerate = compose(f1, f2, f3) # f1, f2, f3 are functions

class Y(X):
move = compose(f4, f5)
stop = f6

class Z(Y):
action = compose(accelerate, stop)

class U(Y):
action = compose(move, stop)

这些类根本不会被初始化;我只是想使用它们来创建功能层次结构。

最佳答案

当你这样写的时候:

class B(A):
b = 2
y = b # works fine
x = a # NameError: name 'a' is not defined
x = A.a # works fine

Python 所做的是创建一个新范围(存储在字典中),执行所有定义,然后在类 block 的末尾将字典传递给 type 类(除非您已经设置了另一个元类)来创建你的新类。它大致等同于:

B = type('B', (A,), classdict_from_scope)

在您到达那个阶段之前,B 类不存在,更不用说有任何基类可以从中继承属性了。考虑到您可能有多个基类,并且在这些类中查找名称的解析顺序很复杂,并且取决于它们的完整集合及其所有基类;在您的子类 B 实际创建之前,此顺序不会确定。

这意味着当 Python 开始执行 x = a 时,它发现 a 不在范围内,并且它没有在类或实例上进行属性查找,所以它不能遵循名称解析协议(protocol)来寻找替代绑定(bind)。所以它所能做的就是抛出一个错误。

这就是 为什么 Python 以这种方式工作。你能做些什么?

您有两个基本选项。

  1. 您可以明确指定要在其中查找属性的类。
  2. 您可以在创建子类后查找其属性。

请注意,如果您仅使用单一继承,则 (1) 并没有那么糟糕;您可以只查找 A 中的所有属性;如果它们仅在 A 的父类中定义,这仍然会找到它们,因此您实际上不需要知道它们在层次结构中的何处定义。

如果您有多重继承,那么您至少必须知道哪个层次结构包含您要查找的属性。如果这很困难或不可能,那么您可以使用选项 (2),它看起来像这样:

class B(A):
b = 2
y = b

B.x = B.a

这看起来有点难看,但是构造了一个相同的类 B,就像您在类 block 中创建 x 和 transient 类 B如果将 B.x 赋值直接放在类 block 之后,则没有 x 永远不会被任何其他代码看到。 (不过,如果您使用类装饰器,它可能不会有相同的结果)

关于python - 为什么父类(super class)属性在当前类的命名空间中不可用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8998608/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com