In C there's a clever trick that lets you avoid pyramid-style code by turning:
在C中有一个聪明的技巧,让你通过转向避免金字塔式代码:
if (check1())
if (check2())
if (check3())
do_something();
into:
成:
do {
if (!check1())
break;
if (!check2())
break;
if (!check3())
break;
do_something();
} while (0);
What's the cleanest way for me to do this in Python, which doesn't have a do-while construct?
在Python中没有do-while构造的最简洁的方法是什么?
Note: I'm not necessarily asking for a way to implement a do-while loop in Python, but a technique to avoid the aforementioned pyramid-style code.
注意:我不一定要求在Python中实现do-while循环的方法,而是一种避免上述金字塔样式代码的技术。
Update: It seems there's some confusion. The only reason I'm using a loop is to be able to break out at any point in the body, which is only supposed to be executed once.
更新:似乎有一些混乱。我使用循环的唯一原因是能够在身体的任何一点突破,这应该只执行一次。
Essentially what I'm doing in Python is this:
基本上我在Python中做的是:
while True:
if not check1():
break
if not check2():
break
if not check3():
break
do_domething()
break
I'm just wondering if there's a cleaner way.
我只是想知道是否有更清洁的方式。
8 个解决方案
#1
-3
In C, the use of the do ... while(0)
construct that you have shown is usually used when the C programmer wants something that behaves like a goto
, but using an actual goto
is out of the question (for various reasons). So, the break
out of the do ... while(0)
is really a kind of hack. Using the same idiom in Python would be perpetuating that hack.
在C中,当C程序员想要一些行为类似于goto的东西时,通常会使用你所显示的do ... while(0)结构,但使用实际的goto是不可能的(出于各种原因) 。所以,do ... while(0)的突破实际上是一种黑客攻击。在Python中使用相同的习惯用法将使黑客行为永久化。
In C, I would generally avoid using this particular use of do ... while(0)
, and instead opt for a checking function. In Python, this would be:
在C中,我通常会避免使用do ... while(0),而是选择检查函数。在Python中,这将是:
def do_checks():
if not check1():
return False
if not check2():
return False
if not check3():
return False
return True
if do_checks():
do_something()
Probably the most direct translation of C's do ... while(0)
construct would be a loop with a single iteration. Don't do this.
可能是C的最直接的转换... while(0)构造将是一个循环,只有一次迭代。不要这样做。
for x in range(1):
if not check1():
break
if not check2():
break
if not check3():
break
do_something()
#2
7
The Pythonic way of writing this would be
Pythonic的写作方式是
if check1() and check2() and check3():
do_something()
In Python we emphasize clarity and simplicity of the code, not using clever programming tricks.
在Python中,我们强调代码的清晰性和简单性,而不是使用聪明的编程技巧。
[Edit] If you need to "create a variable and use it in the first check", then you would use the pyramid-style:
[编辑]如果您需要“创建变量并在第一次检查中使用它”,那么您将使用金字塔样式:
if check1():
#variables and stuff here
if check2():
#variables and stuff here
if check3():
doSomething()
Or, as @Blender suggests, refactor it into a separate method. These are all much simpler and clearer ways of communicating your intent than using a loop that's not intended to loop.
或者,正如@Blender建议的那样,将其重构为一个单独的方法。与使用不打算循环的循环相比,这些都是更简单,更清晰的方式来传达您的意图。
#3
5
Invert your conditions and break out early. If you structure your code well, you won't have to worry about if
staircases in the first place:
颠倒你的条件,尽早爆发。如果你很好地构建你的代码,你不必担心第一个阶段是否有阶梯:
def do_bigger_something():
if not check1():
return
if not check2():
return
if not check3():
return
do_something()
There's a good chance that if one portion of your code does a lot of these checks, it should be turned into a function anyways.
很有可能如果你的代码的一部分做了很多这些检查,那么它应该转变成一个函数。
#4
2
if (check1() and check2() and check3()):
do_something()
#5
1
if check1() and check2() and check3():
do_something()
#6
1
I'd say if the checks are not as trivial as this (which can be done with a simple and
), refactor your code and break it out into a function instead of mis-using a loop for things it's not meant to do;
我会说,如果检查不是那么简单(可以用简单的方法完成),重构代码并将其分解为函数,而不是错误地使用循环来处理它本不应该做的事情;
def doSomethingIfConditions():
if not check1():
return
if not check2():
return
if not check3():
return
doSomething()
...your code...
doSomethingOnConditions()
...your code...
#7
0
Solution #1 (straightforward):
解决方案#1(直截了当):
while True:
if not check1():
break
if not check2():
break
if not check3():
break
do_something()
break
Solution #2 (more pythonic):
解决方案#2(更pythonic):
for check in check1, check2, check3:
if not check():
break
else:
# the else part is only executed
# if we didn't break out the loop
do_something()
Solution #3 (even more pythonic):
解决方案#3(更加pythonic):
if all(c() for c in check1,check2, check3):
# all(seq) will stop at the first false result
do_something()
#8
0
I do not see the need for a loop... You break out of it at the end anyways.
我没有看到需要一个循环...你最后还是打破了它。
if all((check1(), check2(), check3())):
print "Do something"
Or just go with the block-style if it's needed.
或者如果需要,可以选择块式。
#1
-3
In C, the use of the do ... while(0)
construct that you have shown is usually used when the C programmer wants something that behaves like a goto
, but using an actual goto
is out of the question (for various reasons). So, the break
out of the do ... while(0)
is really a kind of hack. Using the same idiom in Python would be perpetuating that hack.
在C中,当C程序员想要一些行为类似于goto的东西时,通常会使用你所显示的do ... while(0)结构,但使用实际的goto是不可能的(出于各种原因) 。所以,do ... while(0)的突破实际上是一种黑客攻击。在Python中使用相同的习惯用法将使黑客行为永久化。
In C, I would generally avoid using this particular use of do ... while(0)
, and instead opt for a checking function. In Python, this would be:
在C中,我通常会避免使用do ... while(0),而是选择检查函数。在Python中,这将是:
def do_checks():
if not check1():
return False
if not check2():
return False
if not check3():
return False
return True
if do_checks():
do_something()
Probably the most direct translation of C's do ... while(0)
construct would be a loop with a single iteration. Don't do this.
可能是C的最直接的转换... while(0)构造将是一个循环,只有一次迭代。不要这样做。
for x in range(1):
if not check1():
break
if not check2():
break
if not check3():
break
do_something()
#2
7
The Pythonic way of writing this would be
Pythonic的写作方式是
if check1() and check2() and check3():
do_something()
In Python we emphasize clarity and simplicity of the code, not using clever programming tricks.
在Python中,我们强调代码的清晰性和简单性,而不是使用聪明的编程技巧。
[Edit] If you need to "create a variable and use it in the first check", then you would use the pyramid-style:
[编辑]如果您需要“创建变量并在第一次检查中使用它”,那么您将使用金字塔样式:
if check1():
#variables and stuff here
if check2():
#variables and stuff here
if check3():
doSomething()
Or, as @Blender suggests, refactor it into a separate method. These are all much simpler and clearer ways of communicating your intent than using a loop that's not intended to loop.
或者,正如@Blender建议的那样,将其重构为一个单独的方法。与使用不打算循环的循环相比,这些都是更简单,更清晰的方式来传达您的意图。
#3
5
Invert your conditions and break out early. If you structure your code well, you won't have to worry about if
staircases in the first place:
颠倒你的条件,尽早爆发。如果你很好地构建你的代码,你不必担心第一个阶段是否有阶梯:
def do_bigger_something():
if not check1():
return
if not check2():
return
if not check3():
return
do_something()
There's a good chance that if one portion of your code does a lot of these checks, it should be turned into a function anyways.
很有可能如果你的代码的一部分做了很多这些检查,那么它应该转变成一个函数。
#4
2
if (check1() and check2() and check3()):
do_something()
#5
1
if check1() and check2() and check3():
do_something()
#6
1
I'd say if the checks are not as trivial as this (which can be done with a simple and
), refactor your code and break it out into a function instead of mis-using a loop for things it's not meant to do;
我会说,如果检查不是那么简单(可以用简单的方法完成),重构代码并将其分解为函数,而不是错误地使用循环来处理它本不应该做的事情;
def doSomethingIfConditions():
if not check1():
return
if not check2():
return
if not check3():
return
doSomething()
...your code...
doSomethingOnConditions()
...your code...
#7
0
Solution #1 (straightforward):
解决方案#1(直截了当):
while True:
if not check1():
break
if not check2():
break
if not check3():
break
do_something()
break
Solution #2 (more pythonic):
解决方案#2(更pythonic):
for check in check1, check2, check3:
if not check():
break
else:
# the else part is only executed
# if we didn't break out the loop
do_something()
Solution #3 (even more pythonic):
解决方案#3(更加pythonic):
if all(c() for c in check1,check2, check3):
# all(seq) will stop at the first false result
do_something()
#8
0
I do not see the need for a loop... You break out of it at the end anyways.
我没有看到需要一个循环...你最后还是打破了它。
if all((check1(), check2(), check3())):
print "Do something"
Or just go with the block-style if it's needed.
或者如果需要,可以选择块式。