我是Python的新手,所以我不确定函数定义之前或之后变量赋值的区别。
具体来说,第一个例子是从Lutz的书中采用的。
def tester(start):
print("inside tester")
def nested(label):
print("inside nested")
print(label,nested.state)
nested.state += 1
print("done with nested")
nested.state = start
print("done with tester")
return nested
F = tester(0)
F('spam')
F.state
F.state
代码的目标是在不使用nonlocal
的情况下存储状态信息。
我不确定nested.state
在这里的含义。我不确定,因为nested.state
在nested()
函数(即nested.state +=1
)和nested()
函数内部(即nested.state = start
)内使用。
我修改了上面的代码,看看Python是否接受nested()
函数声明后的赋值变量,看看是否有任何与function.variable
调用相关的概念(即nested.state
}呼叫)。
def tester(start):
def nested(label):
print(label, state)
state += 1 #replaced 'nested.state' with 'state' here
state = start #replaced 'nested.state' with 'state' here
return nested
F=tester(0)
F('spam')
F('ham')
不幸的是,上面的代码会生成错误local variable 'state' referenced before assignment
。这告诉我,我遗漏了一些关于function.variable
的概念(即nested.state
)。
有人可以帮我理解三件事:
我。为什么nested.state
的代码不会生成任何错误但state
会产生错误?
II。 nested.state
是什么意思?如果nested.state
是一种访问函数变量的机制,为什么nested()
函数中的调用也使用nested.state
而不是state
?
III。如果nested.state
是一种访问函数内部变量的机制,那么当我输入 {时,为什么PyCharm无法在下拉列表中显示state
{1}}
我很感激任何帮助。我研究SO,并且无法找到有关此类问题的任何解释。
答案 0 :(得分:1)
第一个代码示例有效的原因是分配和引用nested
函数对象的属性。这里要理解的关键概念是, Python允许您将新,任意属性分配给对象 - 包括函数 :
>>> def func(a, b):
return a + b
>>> func(1, 2)
3
>>> func.attr = 5
>>> func.attr
5
第一个代码示例通过使用nested
函数对象来存储必要的状态来利用这一事实。这与使用任何其他对象来存储状态的概念相同。然而,使用功能特别方便,因为它很容易获得。
在第二个示例中,使用了一个普通变量。因此,正常的范围规则适用,这意味着state
中定义的tester
变量不是 state
中引用的nested
变量。因此,引发了错误。
答案 1 :(得分:0)
实际上,我认为您在Python中询问有关范围的问题,忽略了您的代码,请检查:
def scope_level_1():
variable = 'Scope_level_1'
def scope_level_2():
variable = 'Scope_level_2'
def core():
nonlocal variable
variable += '_TOUCHED_AND_MODIFIED_BY_CORE'
print(variable)
return core()
return scope_level_2()
scope_level_1()
# 'Scope_level_2_TOUCHED_AND_MODIFIED_BY_CORE'
不要担心关键字nonlocal,将其视为声明使代码更具可读性。
答案 2 :(得分:0)
首先,请记住a += b
与a = a + b
相同。因此,a
必须存在才能进入+=
。
简单地说,在第一个示例中,函数nested
具有一个名为state
的属性(由nested.state
访问)。这是一个属性,这意味着一旦你告诉nested
它有一个名为state
的属性(你在nested.state = start
时在第9行执行此操作),它就会保留该属性。因此,当您到达nested.state
时,在第一个示例中+=
存在。
在第二个示例中,您在state
中声明了一个名为tester
的变量,在state
中声明了一个名为nested
的变量。 nested
中的那个可以被称为potato
,因为它不是同一个变量。因此,当您到达+=
时,变量state
不存在!