在处理一个足够大的 Python 文件时,我意外地重新定义了全局范围内的一个函数。如果 Python 解释器可以在这些情况下警告我,我将不胜感激。
想象一下你从此代码(版本 1)开始:
#!/usr/bin/env python ... lots of code ... def foo(version): if version == 1: return "Correct" return "Oops!" ... lots more code ... print foo(1)
哪个工作正常:
Correct
然后你想改变一些东西,并称之为版本 2。你重写了 foo 函数,但你要么没有意识到旧函数的存在,要么你忘记删除它。你最终得到这样的结果:
#!/usr/bin/env python def foo(version): if version == 2: return "Correct" return "Oops!" ... lots of code ... def foo(version): if version == 1: return "Correct" return "Oops!" ... lots more code ... print foo(2)
效果不太好:
Oops!
我知道 python 允许这样的代码:
def monkey(): return "patching" monkey = "is" def monkey(): return {"really": "fun"}
但似乎以这种方式使用“def”是一种不好的做法。
有什么办法可以得到这种行为:
#!/usr/bin/env python --def-strict def foo(): pass def foo(): pass
结果:
Traceback (most recent call last): File ..., line 3, in <module> NameError: name 'foo' is already defined
Python 本身并不提供一个内置的标志来防止函数的重新定义。但你可以通过以下几种方法来检测并警告此类情况:
可以使用一个装饰器来检测是否有重复定义的函数。装饰器会检查函数名是否已在全局命名空间中存在:
import functools import warnings def check_redefine(func): global_namespace = globals() if func.__name__ in global_namespace: warnings.warn(f"Function '{func.__name__}' is already defined", SyntaxWarning) global_namespace[func.__name__] = func return func @check_redefine def foo(version): if version == 1: return "Correct" return "Oops!" # Simulate a redefinition @check_redefine def foo(version): if version == 2: return "Correct" return "Oops!"
当你运行此代码时,如果 foo 已经在命名空间中定义,check_redefine 装饰器会发出警告。
foo
check_redefine
flake8
pylint
静态代码分析工具如 flake8 和 pylint 可以帮助发现重复的函数定义。这些工具会在代码分析时发出警告,从而帮助你在执行代码前检测到问题。
你可以在模块加载时手动检查重复定义,这样在模块被加载或重新加载时会立即提示。
import sys module_functions = set() def define_function(func): if func.__name__ in module_functions: raise NameError(f"Function '{func.__name__}' is already defined") module_functions.add(func.__name__) return func @define_function def foo(version): if version == 1: return "Correct" return "Oops!" # Simulate a redefinition @define_function def foo(version): if version == 2: return "Correct" return "Oops!"
在这种实现中,define_function 检查是否有相同名称的函数已存在,从而在发现重复定义时抛出 NameError。
define_function
NameError
__future__
虽然 __future__ 模块无法直接启用严格模式,但你可以在入口文件中控制导入的函数,避免不必要的覆盖,并保持命名空间的清晰。