这篇文章翻译自activecode的文章Variable Abbreviations
这篇文章属于简书专题Python Recipe
变量有时可能会有一个很长的易读的名称,比如buildingList[foundIndex].height
,不过在一些类似公式或类似的情况下,如果出现太多过长名称的变量可能会搞混读者。物理学家出于这个原因使用"单字母变量名(one-letter names)"。
出于这个原因,我写了一个简单的上下文管理器。可以使用简单的变量名来代替长变量名:
with Abbr(h=buildingList[foundIndex].height, g=gravitationalConstant):
fallTime = sqrt(2 * h / g)
endSpeed = sqrt(2 * h * g)
print("Fall time:", fallTime)
print("End speed:", endSpeed)
对于较长公式来说,这种方式可以减少那种丑陋的多行表达式的情况。
也可以这样写:
h = buildingList[foundIndex].height
g = gravitationalConstant
fallTime = sqrt(2 * h / g)
endSpeed = sqrt(2 * h * g)
del g, h
print("Fall time:", fallTime)
print("End speed:", endSpeed)
上面的代码可以达到相同的效果,不过:
- 后者看起来不如前者那么清晰
- 上下文管理器的方式可以像一般处理exception那样清理变量
当然,你也可以选择不删除那些短的局部变量,但是这会搞乱命名空间。
警告:Abbr()
是以hack的方式实现的。它是为了本文讨论的目的而实现的。但是因为它的hack,所以有些事情需要提及:由于编译时编译器例子中的h
和g
必须是全局变量(因为不是在函数中赋值),它会生成一个byte code来访问全局变量。上下文管理器会对全局变量结构(globals()
)作些改动。这意味着:
- 不可以在上下文管理的代码块中再赋值一个相同名称的局部变量。
- 在上下文管理器的生命周期内,已存的全局变量将会被修改;所以使用类似
sys
或os
这种缩写名称会造成副作用。
class Abbr(object):
def __init__(self, **kwargs):
self.abbrs = kwargs
self.store = {} # 用来临时存储一些被替换的全局变量
def __enter__(self):
for key, value in self.abbrs.iteritems():
try:
self.store[key] = globals()[key]
except KeyError:
pass
globals()[key] = value
def __exit__(self, *args, **kwargs):
for key in self.abbrs:
try:
globals()[key] = self.store[key]
except KeyError:
del globals()[key]
网友评论