Python:为何重定义函数不是错误?有没有什么变通方法?

8 投票
5 回答
7537 浏览
提问于 2025-04-18 03:16

例如:

def foo():
    print 'first foo'
def foo():
    print 'second foo'

foo()

默默地输出了:second foo

今天我在同一个文件里复制粘贴了一个函数的定义,并且在第二个定义的内容里改了几行,但忘了改函数的名字。我看着输出,挠了很久的头,最后才搞明白是怎么回事。

有没有办法让解释器在重新定义一个函数时至少给我一个警告呢?谢谢!

5 个回答

-1

好吧,你可以这样检查它是否存在

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
0

你需要了解Python中关于对象的基本概念。在Python里,所有东西都是对象。当你创建一个函数时,其实是在创建一个函数这个类的对象,并把它命名为你的函数名。

当你重新定义这个函数时,其实就是用一个新的对象替换掉旧的对象,就像是创建一个同名的新变量一样简单。

例如:

>>> a=10
>>> print a
10
>>> a=20
>>> print a
20

同样,你可以检查这个函数的类。

 >>> def a():
 ...     pass
 ... 
 >>> a.__class__
 <type 'function'>

这说明你的函数实际上是一个对象或变量,可以被同类的其他对象或变量替换。

2

我觉得这和变量(也叫标识符)的行为很像:

In [4]: a = 2

In [5]: a = 3

In [6]: a
Out[6]: 3

你不会看到解释器对a被重新定义而发愁。

编辑 有人下面评论了,我觉得这可以帮助澄清我的回答:

[这是因为] 函数对象和其他对象没有区别对待,而通过def定义的名字和通过其他方式定义的名字也没有区别对待。

关于def是一个保留标识符的内容,可以查看语言参考

3

这是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))。

10

你可以试试使用 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

pydev

撰写回答