我正试图重构一个针对Python3.6和pytest的项目。测试套件包含许多调试语句,例如:
print('This is how something looks right now', random_thing.foo.bar.start,
random_thing.foo.bar.middle, random_thing.foo.bar.end)
这些陈述背后的想法是,如果将来测试开始失败,我们将有一些上下文来帮助我们追踪问题可能是什么。现在不需要测试测试中的实际值,但是一旦事情开始失败,拥有这些信息对于进一步调试很重要
我想避免重复random_thing.foo.bar.
那么多次。我可以将其分配给一个临时变量,但代码并不真正需要该变量。我并不真的担心性能,但我更喜欢保持代码“干净”——而“泄露”这些变量名会让我感到不舒服。在我熟悉的其他语言中,有一个类似的特性,所以我想知道如何在Python中做到这一点
{
const auto& bar = random_thing.foo.bar;
debug << "start: " << bar.start << ", middle: " << bar.middle << ", end: " << bar.end;
}
考虑到there are no anonymous blocks in Python,有没有一种“Pythonic”方法可以避免这种名称空间混乱?我并不是真的在寻找意见或人气竞赛,而是基于比我做Python的时间更长的人对这些方法的看法来进行评论,所以我尝试了以下几点:
del
它就可以了嗯,我不喜欢重复做机器应该为我做的事情
with
语句和^{在Python中,with
语句没有新的作用域,因此opj
变量可以通过局部变量使用:
>>> import os
>>> import os.path
>>> import contextlib
>>> with contextlib.nullcontext(os.path.join) as opj:
... print(type(opj))
...
<class 'function'>
>>> print(type(opj))
<class 'function'>
with
声明和弗拉基米尔·亚科夫列夫的^{from contextlib import contextmanager
from inspect import currentframe, getouterframes
@contextmanager
def let(**bindings):
frame = getouterframes(currentframe(), 2)[-1][0] # 2 because first frame in `contextmanager` is the decorator
locals_ = frame.f_locals
original = {var: locals_.get(var) for var in bindings.keys()}
locals_.update(bindings)
yield
locals_.update(original)
代码在我看来非常棒:
>>> a = 3
>>> b = 4
>>> with let(a=33, b=44):
... print(a, b)
...
(33, 44)
>>> print(a, b)
(3, 4)
它没有undef
以前没有定义过的变量,但是很容易添加。以这种方式操纵堆栈是明智的想法吗?我的Python fu是有限的,所以我在将其视为超级酷和超级黑客之间左右为难。最终的结果是“合理的Python”吗
**kwargs
围绕print
的包装器让我们使用**kwargs
:
def print_me(format, **kwargs):
print(format.format(**kwargs))
print_me('This is it: {bar.start} {bar.middle} {bar.end}', bar=random_thing.foo.bar)
这已经足够好了,但是f-strings可以包含实际表达式,例如:
foo = 10
print(f'{foo + 1}')
我想保留这个功能。我理解^{
您最好的选择是创建变量并将其保留在那里,或者
del
如果它真的让您感到非常困扰,那么之后再创建它with
不是一个可行的方法。特别是let
这件事在多个方面被彻底打破了最重要的错误是,修改
f_locals
是未定义的行为,但由于其他错误,这在测试中并不明显。另外两个错误是2
控制的东西与作者的想法完全无关,[-1]
从错误的一端开始索引。这些错误导致代码访问“根”堆栈帧,即堆栈开头的帧,而不是作者想要的帧。最后,它没有处理实际清除变量的方法-它只能将它们设置为None
如果你test it with a function,你会发现它不起作用:
输出:
3
在本应看到它的代码中不可见,并且有一个额外的None
挂在错误的范围中没有好的方法可以从
with
语句中获得您想要的功能。默认的with
作用域规则不能满足您的需要,Python也不能让上下文管理器处理调用它的代码的局部如果您确实讨厌该变量,并且不想使用
del
,那么最接近于一个好的选择可能是使用立即调用lambda的Javascript样式:我认为这个选项比普通方式分配
x
要糟糕得多,但你可能会有不同的想法这里有一点乐趣
输出:
相关问题 更多 >
编程相关推荐