python 2.7.3 中函数和局部变量名称相同的行为不一致
Inconsistent behavior in python 2.7.3 with same name of function and local variable
今天我发现以下代码有一些奇怪的行为:
if (arg == 0):
# some local variable
format = ""
ret = format + arg
else:
# bultin format function
ret = format(arg, "#x")
print ret
它起着内外不同的作用。
使用此代码:
import sys
def foo(arg):
if (arg == 0):
# some local variable
format = ""
ret = format + "0"
else:
# bultin format function
ret = format(arg, "#x")
print ret
arg = int(sys.argv[1])
print "Outside function:"
if (arg == 0):
# some local variable
format = ""
ret = format + "0"
else:
# bultin format function
ret = format(arg, "#x")
print ret
print "Foo call:"
foo(arg)
我得到以下调用输出:python format.py 1
Outside function:
0x1
Foo call:
Traceback (most recent call last):
File "format.py", line 31, in <module>
foo(arg)
File "format.py", line 10, in foo
ret = format(arg, "#x")
第一个问题是为什么if语句下的一个局部变量隐藏了else语句中使用的格式化函数?
第二个是为什么在函数外部调用时它的行为不同(现在具有预期的行为)?
Python 区分全局变量和局部变量;在函数外,format
是全局的,在函数内,format
是局部的 因为你给它赋值(如果你从未在函数中的任何地方绑定名称函数,它将被视为全局函数)。您不能同时将名称视为全局名称和本地名称。
if
在这里无关紧要;名称可见性适用于 整个范围 ; if
没有引入新的作用域,只有函数引入了。所以在函数中,format
是局部名称,永远不能作为全局名称查找,无论 if
块如何。
你的代码在函数之外工作,因为已经有一个名为 format
的全局变量;它是一个内置函数。如果 args == 0
为真,您的代码将只工作 一次 因为之后它会将全局变量反弹为字符串,并且以后对 format()
的调用将失败。
在函数内部,format
现在是本地的,如果 args != 0
则永远不会设置;这里的赋值由 if
保护并不重要,它要么是 always 本地的,要么是 always 全局的,因为这是在编译时确定的。
您可以通过不在此处重载名称 format
来轻松避免此问题。您不想一开始就意外地屏蔽名称 format
,因为这会破坏其他想要使用 format()
函数的代码。对于您的具体示例,完全删除 format
的使用是微不足道的:
def foo(arg):
if (arg == 0):
ret = "0"
else:
# bultin format function
ret = format(arg, "#x")
print ret
您甚至可以根据 args
的值更改格式配置:
def foo(arg):
return format(arg, "#x" if args else "d")
今天我发现以下代码有一些奇怪的行为:
if (arg == 0):
# some local variable
format = ""
ret = format + arg
else:
# bultin format function
ret = format(arg, "#x")
print ret
它起着内外不同的作用。 使用此代码:
import sys
def foo(arg):
if (arg == 0):
# some local variable
format = ""
ret = format + "0"
else:
# bultin format function
ret = format(arg, "#x")
print ret
arg = int(sys.argv[1])
print "Outside function:"
if (arg == 0):
# some local variable
format = ""
ret = format + "0"
else:
# bultin format function
ret = format(arg, "#x")
print ret
print "Foo call:"
foo(arg)
我得到以下调用输出:python format.py 1
Outside function:
0x1
Foo call:
Traceback (most recent call last):
File "format.py", line 31, in <module>
foo(arg)
File "format.py", line 10, in foo
ret = format(arg, "#x")
第一个问题是为什么if语句下的一个局部变量隐藏了else语句中使用的格式化函数?
第二个是为什么在函数外部调用时它的行为不同(现在具有预期的行为)?
Python 区分全局变量和局部变量;在函数外,format
是全局的,在函数内,format
是局部的 因为你给它赋值(如果你从未在函数中的任何地方绑定名称函数,它将被视为全局函数)。您不能同时将名称视为全局名称和本地名称。
if
在这里无关紧要;名称可见性适用于 整个范围 ; if
没有引入新的作用域,只有函数引入了。所以在函数中,format
是局部名称,永远不能作为全局名称查找,无论 if
块如何。
你的代码在函数之外工作,因为已经有一个名为 format
的全局变量;它是一个内置函数。如果 args == 0
为真,您的代码将只工作 一次 因为之后它会将全局变量反弹为字符串,并且以后对 format()
的调用将失败。
在函数内部,format
现在是本地的,如果 args != 0
则永远不会设置;这里的赋值由 if
保护并不重要,它要么是 always 本地的,要么是 always 全局的,因为这是在编译时确定的。
您可以通过不在此处重载名称 format
来轻松避免此问题。您不想一开始就意外地屏蔽名称 format
,因为这会破坏其他想要使用 format()
函数的代码。对于您的具体示例,完全删除 format
的使用是微不足道的:
def foo(arg):
if (arg == 0):
ret = "0"
else:
# bultin format function
ret = format(arg, "#x")
print ret
您甚至可以根据 args
的值更改格式配置:
def foo(arg):
return format(arg, "#x" if args else "d")