在函数内部分配变量:奇怪的行为

时间:2016-08-07 04:42:15

标签: 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="sds"
NameError: name 'w' is not defined

3 个答案:

答案 0 :(得分:5)

尝试运行您的功能,看看会发生什么。 Python在编写代码时并没有捕获它,但是一旦运行代码就会出错。

你看到的是因为python不知道当你的函数运行时,它不会成为具有属性#Python 2.7 import string companyName = string.replace(companyName, "'", "") 的对象w。但是,当您在函数调用之外执行此操作时,它会检查范围中是否存在s,从而检查错误。

试试这个:

w

答案 1 :(得分:4)

函数尚未运行,因为它尚未被调用,而不是在函数外部完成w.s"sds"的分配。

答案 2 :(得分:2)

这种行为是允许的,因为Python是一种动态语言。在编译时,当执行f函数定义(即,编译为字节代码)时,解释器知道函数中没有绑定到名称w的本地对象,因此{{1必须引用一个全局对象。当然,当前在全局范围内没有绑定到该名称的对象,但这并不重要:Python假设您知道自己在做什么,直到证明不是这样:)。

我们可以使用dis模块来反汇编函数的字节代码。这是一个简短的演示。

w

<强>输出

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__)

FWIW,在Python 2中, 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'} 的字节代码相同,但f错误消息为
NameException

因此,如果我们在调用时尝试在全局范围内调用global name 'w' is not defined而没有有效的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()