0

在尝试减少嵌套 ifs(以及停止工作的脚本)遇到很多麻烦之后,我意识到我可能对布尔值在 python 中的工作方式和工作方式有错误的想法。

我有这个(工作正常但扭曲):

if (not gotside):
    if (j > 1):
        if (j < a.shape[1] - 1):
            if a[i, j+unit]:
                print "only now I do stuff!"

并尝试了这个(看起来没有按预期工作而变得简单):

if (not gotside) and (j > 1) and (j < a.shape[1] - 1) and a[i, j+unit]:
    print "I'm well tested but not so indented..."

然后我尝试使用“或”而不是“和”,但没有奏效,因为(后来我发现)当你使用x and y甚至x or y你得到一个x, y,而不是一个True, False,根据文档。

因此,我不知道如何以一种在False第一个测试结果为 False 时整个表达式立即返回的方式一个接一个地进行一些测试(最好在同一行中,使用布尔运算符)。

谢谢阅读!

4

5 回答 5

6

你的例子应该有效。

if x and y and z:
    ...

仅当 x、y 和 z 均未计算为 时才应发生False,并且在 Python 中and为短路,因此False一旦一项失败就会返回该值。我们可以很容易地证明这一点:

>>> def test(n):
...     print("test", n)
...     return n
... 
>>> test(1) and test(2)
test 1
test 2
2
>>> test(0) and test(2)
test 0
0
>>> test(0) and test(2) and test(3)
test 0
0
>>> test(1) and test(0) and test(3)
test 1
test 0
0
于 2012-04-27T18:37:48.993 回答
3

我看到了你的担忧,但请记住,只要ifPython 中的语句中有内容,它将被隐式转换bool为条件。因此,当独立完成时3 or 2返回33 and 2返回,说实际上等同于说,因此无论布尔逻辑在其他上下文中返回什么,在条件中使用时您将获得逻辑返回的错误或真值。2if 3 or 2if bool(3 or 2)

于 2012-04-27T18:44:43.820 回答
3

是的,我必须同意其他人的说法,即您的示例应该按您的意愿工作。您是对的,它x or y返回 x、y 之一,但该对象将能够被评估为 True 或 False。这就是python评估if语句的方式。它应该像所写的那样工作,因为您的表达式将按顺序进行评估,并且一旦该行中的任何测试返回为 False(或 0,或[]{}等),它将返回 False。如果 python 实际尝试过,您可以通过一个会引发错误的测试来看到这一点。

x = 1; y = 2
if x < y and x == y and d['a']: # d doesn't exist
    print 'This will never be printed'

如果您的代码没有按预期工作,请详细说明您期望它做什么以及它实际在做什么。

于 2012-04-27T19:09:37.207 回答
1

Python(以及大多数其他编程语言)中的布尔值和运算符提供“短路”功能。这意味着,如果第一项或表达式的计算结果为 false,则甚至不计算第二项:

>>> False and expensiveFunctionReturningBool()
False

永远不会调用昂贵的函数,因为 Python 解释器在第一项被确定为 False 后立即将表达式评估为 False。这是可行的,因为在布尔逻辑中,如果 and 表达式的一侧为假,则整个表达式根据定义为假

Python 还使用 or 的短路逻辑。在这种情况下,如果第一项被确定为 True,则永远不会评估第二项。

>>> True or expensive()
True

因此,布尔表达式可用于折叠嵌套的 if 语句(前提是它们一个接一个地立即声明),如果通过牢记短路逻辑巧妙地使用它们,它们还可以优化条件表达式。

祝你好运!

于 2012-04-27T18:52:16.647 回答
1

我对您未包含的代码做了一些假设,并添加了它以使程序运行:

gotside = False
j = 2
i = 1
unit = 3

class A:
    def __init__(self):
        self.shape = [1, 4]
    def __getitem__(self, pos):
        return pos

a = A()


if (not gotside):
    if (j > 1):
        if (j < a.shape[1] - 1):
            if a[i, j+unit]:
                print("only now I do stuff!")

if (not gotside) and (j > 1) and (j < a.shape[1] - 1) and a[i, j+unit]:
   print("I'm well tested but not so indented...")

对我来说,这适用于 python 2.5、2.6、2.7 和 3.2:

only now I do stuff!
I'm well tested but not so indented...

如果这对你有用,你能检查一下上面的程序吗?如果是这样,您能否提供有关您使用的类的更多信息 - 特别是变量类a

于 2012-04-27T19:05:54.800 回答