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

mic*_*ang 0 python constructor arguments class class-attributes

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

file test.py:

class Foo:
    var1 = 23333
    def __init__(self, var=var1):
        self.var = var
Run Code Online (Sandbox Code Playgroud)

在cmd中运行:

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

但是通过使用dot.expression,当init这个类时,解释器将报告错误:

文件test2.py:

class Foo:
    var1 = 23333
    def __init__(self, var=Foo.var1):
       self.var = var
Run Code Online (Sandbox Code Playgroud)

在cmd中运行:

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
Run Code Online (Sandbox Code Playgroud)

我只是不知道为什么解释器找不到名字'Foo',因为Foo是环境中全局框架中的名字.有什么关于python类的范围相关的概念,我不完全理解?

Mar*_*ers 6

函数默认值在函数定义时设置,而不是在被调用时设置.因此,它不是var1存储的表达式,而是变量所代表的,23333.var1在定义函数时,它恰好是一个局部变量,因为在构建类时,类体中的所有名称都被视为函数中的局部变量,但Foo由于该类尚未完成构建,因此该名称尚不存在.

改为使用sentinel,然后在函数体中确定当前值Foo.var1:

def __init__(self, var=None):
    if var is None:
        var = Foo.var1
    self.var = var
Run Code Online (Sandbox Code Playgroud)

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

_sentinel = object()

class Foo:
    var = 23333

    def __init__(self, var=_sentinel):
        if var is _sentinel:
            var = Foo.var1
        self.var = var
Run Code Online (Sandbox Code Playgroud)