Python:为何重定义函数不是错误?有没有什么变通方法?
例如:
def foo():
print 'first foo'
def foo():
print 'second foo'
foo()
默默地输出了:second foo
今天我在同一个文件里复制粘贴了一个函数的定义,并且在第二个定义的内容里改了几行,但忘了改函数的名字。我看着输出,挠了很久的头,最后才搞明白是怎么回事。
有没有办法让解释器在重新定义一个函数时至少给我一个警告呢?谢谢!
5 个回答
好吧,你可以这样检查它是否存在
def foo():
pass
def check_foo(variable_dict):
if 'foo' in variable_dict:
print('Function foo already exists!')
else:
print('Function foo does not exist..')
>>> check_foo()
True
>>> del foo
>>> check_foo(locals())
False
你需要了解Python中关于对象的基本概念。在Python里,所有东西都是对象。当你创建一个函数时,其实是在创建一个函数这个类的对象,并把它命名为你的函数名。
当你重新定义这个函数时,其实就是用一个新的对象替换掉旧的对象,就像是创建一个同名的新变量一样简单。
例如:
>>> a=10
>>> print a
10
>>> a=20
>>> print a
20
同样,你可以检查这个函数的类。
>>> def a():
... pass
...
>>> a.__class__
<type 'function'>
这说明你的函数实际上是一个对象或变量,可以被同类的其他对象或变量替换。
我觉得这和变量(也叫标识符)的行为很像:
In [4]: a = 2
In [5]: a = 3
In [6]: a
Out[6]: 3
你不会看到解释器对a
被重新定义而发愁。
编辑 有人下面评论了,我觉得这可以帮助澄清我的回答:
[这是因为] 函数对象和其他对象没有区别对待,而通过
def
定义的名字和通过其他方式定义的名字也没有区别对待。
关于def
是一个保留标识符的内容,可以查看语言参考。
这是Python的一项特性。函数和整数一样都是值,所以你可以像在C++中使用函数指针那样,把它们传来传去,或者重新绑定到不同的名字上。
看看这段代码:
def foo(): # we define function and bind func object to name 'foo'
print "this if foo"
foo() # >>>this if foo
bar = foo # we bind name 'bar' to the same function object
def foo(): # new function object is created and bound to foo
print "this is new foo"
foo() # foo now points to new object
# >>>this is new foo
bar() # but old function object is still unmodified:
# >>>this if foo
所以解释器运行得很好。实际上,在使用交互式解释器时,重新定义函数是很常见的,直到你把它搞对为止。或者在使用装饰器的时候也是如此。
如果你想在Python中重新定义某些东西时收到警告,可以使用一些'lint'工具,比如pylint(查看函数重新定义的警告 (E0102))。
你可以试试使用 pylint
吗?
pylint your_code.py
假设你的文件叫做 your_code.py
,内容是
1 def dup():
2 print 'a'
3 def dup():
4 print 'a'
5
6 dup()
pylint
会显示一些信息
C: 1,0: Missing docstring
C: 1,0:dup: Missing docstring
E: 3,0:dup: function already defined line 1 <--- HERE!!!!
C: 3,0:dup: Missing docstring
...
如果你在使用 Pydev
,你可以通过交互的方式找到重复的代码。
当你把鼠标放在第二个 dup
上时,它会提示 Duplicated signature: dup
。