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

2024-04-20 06:05:05 发布

您现在位置:Python中文网/ 问答频道 /正文

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

def foo(l=[]):
    l.append(1)
    print(l)

foo()
foo()
foo([])
foo()

打印以下内容。你知道吗

[1]
[1,1]
[1]
[1,1,1]

所以我对它们作为对象初始化器的使用持怀疑态度。 最近我遇到了另一个类似的奇怪行为, 演示如下。你知道吗

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

这会引发异常,因为bar未在此命名空间中定义。你知道吗

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

现在,它成功地将类变量foo持有的值分配给初始化器内的对象a。 为什么会发生这些事情?默认参数值是如何处理的?你知道吗


Tags: 对象self名称fooinitdef方式bar
1条回答
网友
1楼 · 发布于 2024-04-20 06:05:05

三个事实:

  1. 默认参数的名称(左侧)是函数体中的局部变量名称。你知道吗
  2. 在定义函数时,默认参数的(右侧)在定义函数的范围内进行求值。你知道吗
  3. 类块中的代码在类定义期间在临时命名空间中执行。类块没有被视为封闭作用域,如果您期望的行为类似于嵌套的def,这可能会令人惊讶。你知道吗

第三点是最微妙的,也许与最初的预期相反。它记录在execution model(第4.2.2节)。姓名解析(英文):

The scope of names defined in a class block is limited to the class block; it does not extend to the code blocks of methods

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

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

注意,bar0仍然可以作为类属性从方法中访问:通过Foo.barself.bar。你知道吗

现在,您应该了解最后一个示例的工作原理:

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

而且,考虑到上面的1-3点,你也应该能够正确地预测这里发生了什么:

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

UnboundLocalError: local variable referenced before assignment why LEGB Rule not applied in this case中有关于怪异类作用域的更多信息。你知道吗

相关问题 更多 >