python class 属性不能用作构造函数的参数?

python class attribute cannot used as an argument for constructor?

在python 3中我发现class属性可以用作__init__()函数中的参数,如下所示:

文件test.py:

class Foo:
    var1 = 23333
    def __init__(self, var=var1):
        self.var = var

运行 在命令中:

C:\Users\rikka\Desktop>py -3 -i test.py
>>> f1=Foo()
>>> f1.var
23333

但是通过使用dot.expression,当初始化这个class时,解释器会报错:

文件test2.py:

class Foo:
    var1 = 23333
    def __init__(self, var=Foo.var1):
       self.var = var

运行 在命令中:

C:\Users\rikka\Desktop>py -3 -i test2.py
Traceback (most recent call last):
  File "test2.py", line 1, in <module>
    class Foo:
  File "test2.py", line 3, in Foo
    def __init__(self, var=Foo.var1):
NameError: name 'Foo' is not defined

我只是不知道为什么解释器找不到名称 'Foo' 因为 Foo 是环境中全局框架中的名称。关于 python class 是否有一些我不完全理解的与范围相关的概念?

函数默认值在函数定义时设置,而不是在调用时设置。因此,存储的不是表达式 var1,而是变量表示的 23333var1 在定义函数时恰好是一个局部变量,因为 所有 名称在 class 主体中被视为函数中的局部变量,当 class 已构建,但名称 Foo 尚不存在,因为 class 尚未完成构建。

改用哨兵,在函数体内然后判断Foo.var1的当前值:

def __init__(self, var=None):
    if var is None:
        var = Foo.var1
    self.var = var

我在这里使用 None 作为标记,因为它很容易获得并且不经常需要作为实际值。如果您确实需要能够将 var 设置为不同的(即非默认)值,请使用不同的单例标记:

_sentinel = object()

class Foo:
    var = 23333

    def __init__(self, var=_sentinel):
        if var is _sentinel:
            var = Foo.var1
        self.var = var

问题是您试图在 Foo 的构造过程中引用它。在定义 Foo.__init__ 的那一刻,也就是评估 Foo.var 时,Foo 还不存在(因为它的方法,即 Foo.__init__ 本身,还没有完全构建还没有)。

Function/method 默认参数在 function/method 定义期间解析。 类 仅在定义后可用。如果 class 方法定义(即参数)引用了 class 本身,就会产生循环依赖。没有class就不能定义方法,没有方法就不能定义class。

请参阅 Martijn Pieters 的回复,了解如何实际处理此类依赖关系。