我想这有点滥用该功能,但我仍然很好奇它是否可以完成 - 我想做类似的事情:
with conditional(a):
print 1
以便print 1
仅当 a==True 时才执行该部分。这可能吗?
编辑:就像下面的人所说,这是一种可怕的风格。这只是一个谜\问题。不要在家里尝试这个,不适合胆小的人等。
我想这有点滥用该功能,但我仍然很好奇它是否可以完成 - 我想做类似的事情:
with conditional(a):
print 1
以便print 1
仅当 a==True 时才执行该部分。这可能吗?
编辑:就像下面的人所说,这是一种可怕的风格。这只是一个谜\问题。不要在家里尝试这个,不适合胆小的人等。
没有真正的理由这样做,因为已经使用以下if
语句提供了条件:
if a == True:
print 1
但是,如果你只是想找点乐子,答案是你真的做不到。要停止with
执行内容,conditional
需要在其__enter__
方法中以某种方式停止执行。但它可以做到这一点的唯一方法是引发异常,这意味着没有其他代码将运行,除非你with
用try
语句包装处理案例a != True
编辑:看到我在评论和投票中因使用 OP 的条件 ( a == True
) 而被起诉,我考虑将其更改为if a
,这当然是 Python 中用于测试条件的成语。但是,我们不知道OP 的想法是什么,以及他是否真的想a
成为一个布尔值,并且不希望 block 执行如果a = [1]
(它将通过if a
)我决定保持原样。
if a is True:
print 1
with
语句旨在提供可靠的进入退出上下文。
conditional
我看到的唯一方法是在其论点为假时引发异常。with
正文不会被执行,但后面的任何代码也不会被执行——当然,直到一个orexcept
子句finally
。
假设我有一个带有 __enter__ 和 __exit__ 函数的 A 类:
class A:
def __init__(self, i):
self.b = i
def __exit__(*args, **kwargs):
print "exit"
def __enter__(*args, **kwargs):
print "enter"
还有一个函数 B,它将检查对象 c 中的 b 是否等于 1,否则它将通过。
def b(c):
if c.b == 1:
return c
else:
pass
我可以实现:
with b(A(1)):
print 10
enter
10
exit
但是如果 b 传递,它将抛出一个 AttributeError ,因为with没有任何东西可以使用。一个解决方案是将with b(A(1)):
内部放入一个 try/except 块。但我不建议这样做。
就个人而言,我确实有条件 with 语句的用例。就我而言,如果尚未完成,我想执行一些工作,然后将其标记为已完成。天真的代码:
if not job_done_file.exists():
commands
on multiple
lines
job_done_file.touch()
这样做的问题是,你很容易忘记touch()
最后的,而且不得不写job_done_file
两次也很烦人。
在 C++ 中,我可以这样做:
template <typename Function>void do_job(Function func, Path & job_done_file) {
if (!job_done_file.exists()) {
func();
job_done_file.touch();
}
}
…
do_job([]() {
commands;
on multiple;
lines;
}, "/path/to/job_done_file");
然而,在 Python 中,一个 lambda 只能由一行组成,并且它必须有一个返回值。因此,我必须编写一个完整的函数作为函数引用传递,即使我可能在整个程序中只使用该函数一次。
我做的是这样的:
@contextmanager
def do_job(job_done_file):
yield not job_done_file.exists()
job_done_file.touch()
…
with do_job('/path/to/job_done_file') as not_done:
if not_done:
commands
on multiple
lines