python中的冲突变量和函数名称

sas*_*llo 3 python

假设我有以下功能:

def xplusy(x, y):
    return x+y

def xplus1(x):
    xplusy = xplusy(x, 1)
    return xplusy
Run Code Online (Sandbox Code Playgroud)

现在,如果我调用a = xplus1(4)它会抛出以下错误:

UnboundLocalError: local variable 'xplusy' referenced before assignment
Run Code Online (Sandbox Code Playgroud)

该错误是由于命名冲突,如果我重新定义xplus1如下:

def xplus1(x):
    s = xplusy(x, 1)
    return s
Run Code Online (Sandbox Code Playgroud)

它工作正常.

为什么会这样:无法正确区分变量和函数调用?

有什么方法吗?

Kyl*_*and 13

在Python中,函数是数据,键入是动态的.这意味着以下行是有效的Python:

def func(x):
    return x + 3

func = 3
Run Code Online (Sandbox Code Playgroud)

func现在是一个int.func不再引用原始函数.func最初是函数的事实与将来可以为其分配什么类型的数据无关.(这就是"动态打字"的意思.)

因此,由于没有静态类型,并且"function"是有效的数据类型,因此Python解释器区分函数和同名引用的数据是没有意义的.因此,在给定的范围内,没有办法使用相同的非限定变量名来表示两个不同的东西.

在您的特定情况下,如果xplus1函数中的代码含义,则意味着"计算值xplusy(x,1)并将该值赋给变量xplusy- 从而丢失对函数 的引用xplusy." 但是,在函数范围内,解释器不允许您对该范围之外的变量进行赋值,因此它假定通过编写赋值语句,您将引入一个新的局部变量xplusy.但是,本地变量尚未定义,因此您尝试调用它会xplusy(x,1)失败.全局定义的函数不会被称为回退,因为同样,您不能使两个非限定名称相同并指向同一范围内的不同数据.


另一个例子展示了"在一个范围内没有重复的变量名称"规则(我实际上只是在尝试构建这个答案时玩弄提示时才发现):

>>> def f1():
...     a = xplusy(3,4)
...     xplusy = 5
...     print xplusy
...
>>> f1()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in f1
UnboundLocalError: local variable 'xplusy' referenced before assignment
>>> def f1():
...     a = xplusy(3,4)
...     print a
...
>>> f1()
7
Run Code Online (Sandbox Code Playgroud)

这表明它确实是范围,而不是需要唯一名称的语句.


编辑:这是一个非常酷的帖子,解释了这个和其他与范围相关的行为:http://me.veekun.com/blog/2011/04/24/gotcha-python-scoping-closures/