在函数内修改全局函数定义是否为不良实践?Python场景咨询
问题分析与解决方案
当前代码的问题
你当前的实现确实属于不良实践,主要问题有以下几点:
- 线程安全风险:修改全局变量
update后,若其他线程同时调用依赖update的函数,会出现意料之外的错误,直到finally块恢复原函数。在多线程环境下这种写法几乎一定会引入隐蔽bug。 - 多余的
deepcopy操作:Python中函数对象是不可变的,deepcopy(update)返回的就是原函数对象本身,因此backup_update is update会返回True,你的assert语句会直接触发错误——你说代码能正常运行,可能实际场景中update并非普通函数,但即便如此,deepcopy在这里完全是冗余操作,直接赋值引用即可。 - 依赖全局状态:这种将函数逻辑与全局变量绑定的写法,可读性极差,维护成本高,后续排查问题时很难定位到全局变量被临时替换的逻辑。
不修改set_func的替代实现
方案1:用上下文管理器封装替换逻辑(单线程友好)
把临时替换全局变量的逻辑封装成上下文管理器,代码更简洁清晰,但仍无法解决多线程问题,适合单线程场景:
from contextlib import contextmanager @contextmanager def temp_replace_global(var_name, new_val): original = globals()[var_name] globals()[var_name] = new_val try: yield finally: globals()[var_name] = original def delete_func(table: str, identifier=None) -> None: with temp_replace_global('update', delete): set_func(table, identifier)
方案2:动态修改代码生成临时函数(hacky但无全局依赖)
通过inspect模块获取set_func的源代码,替换其中的update调用为delete,再动态生成一个临时函数执行。这种方式不依赖全局变量,但对set_func的代码格式有依赖,若set_func的源代码无法获取(比如是C扩展函数)则失效:
import inspect import textwrap def delete_func(table: str, identifier=None) -> None: # 获取set_func的源代码并去除多余缩进 src = textwrap.dedent(inspect.getsource(set_func)) # 替换update调用为delete modified_src = src.replace('update(', 'delete(') # 动态执行代码生成临时函数 local_vars = {} exec(modified_src, globals(), local_vars) temp_func = local_vars['set_func'] # 调用临时函数完成逻辑 temp_func(table, identifier)
方案3:简化版猴子补丁(单线程场景)
保留你的核心逻辑,但去掉冗余的deepcopy和assert,仅做必要的全局替换与恢复:
def delete_func(table: str, identifier=None) -> None: global update original_update = update update = delete try: return set_func(table, identifier) finally: update = original_update
最优建议
如果可以的话,优先修改set_func,将操作函数作为可选参数传入,这才是最优雅、可维护的方案,比如:
def set_func(table: str, identifier=None, **kwargs, operation=update) -> None: ... # does stuff with arguments query = operation(table, kwargs, identifier) ... execute(query) # 此时delete_func可以直接写成: def delete_func(table: str, identifier=None) -> None: set_func(table, identifier, operation=delete)
但你明确要求不能修改set_func,所以只能从上述替代方案中选择适合你场景的实现。
内容的提问来源于stack exchange,提问作者Lucas Napon
相关产品推荐
相关产品推荐

