什么是关键字参数值';python中的名称空间?

什么是关键字参数值';python中的名称空间?,python,python-3.x,arguments,Python,Python 3.x,Arguments,我知道自从我发现了python之后,python以不同的方式对待这个名称空间 def foo(l=[]): l、 附加(1) 印刷品(l) foo() foo() foo([]) foo() 它将打印以下内容 [1] [1,1] [1] [1,1,1] 因此,我对它们作为对象初始值设定项的使用持怀疑态度。 然后最近我遇到了另一个类似的奇怪行为, 如下所示 Foo类: 巴=0 定义初始化(自): self.a=bar Foo() 这会引发一个异常,因为未在此命名空间中定义bar Foo类:

我知道自从我发现了python之后,python以不同的方式对待这个名称空间

def foo(l=[]): l、 附加(1) 印刷品(l) foo() foo() foo([]) foo() 它将打印以下内容

[1]
[1,1]
[1]
[1,1,1]
因此,我对它们作为对象初始值设定项的使用持怀疑态度。 然后最近我遇到了另一个类似的奇怪行为, 如下所示

Foo类:
巴=0
定义初始化(自):
self.a=bar
Foo()
这会引发一个异常,因为未在此命名空间中定义
bar

Foo类:
巴=0
def uuu init uuuu(自,a=bar)
self.a=a
Foo()
现在,它成功地将类变量
foo
持有的值分配给初始值设定项中的对象
a
。 为什么会发生这些事情?默认参数值是如何处理的?

三个事实:

  • 默认参数的名称(左侧)是函数体中的局部变量名称
  • 在定义函数时,默认参数的值(右侧)在定义函数的范围内进行计算
  • 类块中的代码在类定义期间在临时命名空间中执行。类块没有被视为封闭作用域,如果您期望的行为类似于嵌套的
    def
    ,这可能会令人惊讶
  • 第3点是最微妙的,可能与最初的预期相反。其记录在(第4.2.2节名称解析)中:

    类块中定义的名称范围仅限于类块;它不扩展到方法的代码块

    这就是为什么在第二个示例中未解析名称

    class Foo:
        bar = 0
        def __init__(self):
            self.a = bar  # name "bar" isn't accessible here, but code is valid syntax
    
    Foo()  # NameError: name 'bar' is not defined
    
    请注意,
    bar
    值,
    0
    ,仍然可以作为类属性从方法中访问:通过
    Foo.bar
    self.bar

    现在,您应该了解最后一个示例为何有效:

    考虑到以上第1-3点,您还应该能够正确预测此处发生的情况:

    class Foo:
       def __init__(self, a=bar):
           self.a = a
       bar = 0
    Foo()
    

    还有更多关于古怪的类范围的信息。

    类范围中的
    bar
    特性问题与默认值问题有点正交。您需要了解的是,类主体不会形成封闭范围,这就是为什么必须始终在类主体中定义的方法的函数主体内使用
    self.bar
    。还要注意,值本身没有名称空间,不同的名称空间可以引用相同的值。但是,默认值在函数定义时只计算一次,它们可以访问函数定义的范围,无论您使用什么表达式,关于“名称空间”问题,如果您想知道函数的默认参数实际存储在哪里,还可以查看并查找
    \uuuuuu defaults\uuuuuu
    class Foo:
       def __init__(self, a=bar):
           self.a = a
       bar = 0
    Foo()