Python中locals()的使用弊端及更佳替代方案
locals()在该场景下的问题 - 可维护性差:读代码的人看到
'data' in locals()根本没法快速定位data是从哪来的、什么情况下会存在,后续改代码很容易漏逻辑。 - 行为不稳定:Python不同版本、不同优化等级下,
locals()返回的字典不一定和实际局部变量实时同步,极端情况下你以为变量存在,实际读的时候直接抛NameError,或者反过来判断错存在性。 - 本质是在掩盖代码设计问题:正常写代码,局部变量要么是明确传入的参数,要么是在当前作用域提前初始化过的,需要靠查符号表判断变量有没有,说明你前面的分支逻辑没覆盖全,
data只在部分分支里才会被定义,本身就容易出bug。
替代方案
核心原则是别动态查局部变量表,从根源上把变量的定义逻辑理清楚,根据你的代码场景选就行:
- 如果
data是函数的可选入参,直接给个默认值,从根源上不需要判断存在性:
# 给可选参数设置None默认值 def xxx_func(data=None): new_data = None if data is not None: if data.index.freqstr == 'M': new_data = data elif data.index.freqstr in ['D', 'B']: new_data = data.resample('M').last().shift().dropna(how='all') return new_data
- 如果
data是当前作用域里前面的分支逻辑生成的,那就提前在最外层给data初始化个默认值,保证不管走哪个分支,data这个变量一定存在:
# 最外层先初始化,避免变量只在部分分支定义 data = None # ... 这里是你之前可能给data赋值的各种分支逻辑 ... new_data = None if data is not None: if data.index.freqstr == 'M': new_data = data elif data.index.freqstr in ['D', 'B']: new_data = data.resample('M').last().shift().dropna(how='all')
要是你写的是一次性临时脚本,懒得梳理前面的逻辑,也可以用Python推崇的EAFP风格,直接捕获异常处理,比用
locals()靠谱:new_data = None try: if data.index.freqstr == 'M': new_data = data elif data.index.freqstr in ['D','B']: new_data = data.resample('M').last().shift().dropna(how='all') except NameError: # data不存在的时候走这里的逻辑 pass但注意这种写法只适合临时脚本,正式项目里还是推荐前面两种理顺变量作用域的方案,不然后续维护的人很容易踩坑。
内容的提问来源于stack exchange,提问作者worldCurrencies
相关产品推荐
相关产品推荐

