Python 在函数中分配变量:奇怪的行为
我很少使用Python,所以我不清楚为什么允许这种行为: 没有w对象,因此它没有s属性,那么为什么f允许进行Python 在函数中分配变量:奇怪的行为,python,Python,我很少使用Python,所以我不清楚为什么允许这种行为: 没有w对象,因此它没有s属性,那么为什么f允许进行w.s赋值 >>> def f(): w.s="ads" #allows, no exception >>> w.s="sds" #outside function Traceback (most recent call last): File "<pyshell#74>", line 1, in <module>
w.s
赋值
>>> def f():
w.s="ads" #allows, no exception
>>> w.s="sds" #outside function
Traceback (most recent call last):
File "<pyshell#74>", line 1, in <module>
w.s="sds"
NameError: name 'w' is not defined
>>def():
w、 s=“ads”#允许,无例外
>>>w.s=“sds”#外部功能
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
w、 s=“sds”
NameError:未定义名称“w”
试着运行函数,看看会发生什么。Python不会在您编写代码时捕获它,但一旦您运行代码,它就会出错
您所看到的是因为python不知道在函数运行时,不会有一个具有属性s
的对象w
。但是,当您在函数调用之外执行此操作时,它会检查作用域中是否没有w
,从而检查是否存在错误
试试这个:
def f():
w.s = "one"
w.s = "one" # called before there is such an object
f() # called before w exists, it will error out
class SomeClass(object):
def __init__(self):
self.s = "two"
w = SomeClass()
f() # since w exists it will run
函数尚未运行,因为它尚未被调用,而不是在函数外部将
w.s
赋值给“sds”
。这种行为是允许的,因为Python是一种动态语言。在编译时,当执行f
函数定义时(即编译为字节码),解释器知道在绑定到名称w
的函数中没有本地对象,因此w
必须引用全局对象。当然,当前在全局范围中没有绑定到该名称的对象,但这并不重要:Python假定您知道自己在做什么,除非得到证明:)
我们可以使用该模块来反汇编函数的字节码。这里有一个简短的演示
from dis import dis
def f():
w.s = "ads"
dis(f)
print('- ' * 30)
class Test(object):
pass
try:
f()
except Exception as e:
print(e)
w = Test()
f()
print(w.__dict__)
输出
40 0 LOAD_CONST 1 ('ads')
3 LOAD_GLOBAL 0 (w)
6 STORE_ATTR 1 (s)
9 LOAD_CONST 0 (None)
12 RETURN_VALUE
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
name 'w' is not defined
{'s': 'ads'}
name 'w' is not defined
{}
FWIW,在Python 2中,f
的字节码是相同的,但是NameException
错误消息是未定义全局名称“w”
因此,如果我们尝试在调用时在全局范围内调用f()
而没有有效的w
,我们将得到一个异常,但是如果有一个有效的w
则一切正常
请注意,w
必须在全局范围内,另一个函数内的局部w
将不起作用。例如:
def f():
w.s = "ads"
class Test(object):
pass
def g():
w = Test()
try:
f()
except Exception as e:
print(e)
print(w.__dict__)
g()
输出
40 0 LOAD_CONST 1 ('ads')
3 LOAD_GLOBAL 0 (w)
6 STORE_ATTR 1 (s)
9 LOAD_CONST 0 (None)
12 RETURN_VALUE
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
name 'w' is not defined
{'s': 'ads'}
name 'w' is not defined
{}
一旦调用
f()
它将显示相同的错误。除非你没有调用它,否则它不会显示任何错误。对不起,我在匆忙中发布了我的答案,在清除“NameError”后意识到了这一点。非常感谢。