【问题标题】:Is De Morgan's Law Pythonic?德摩根定律是 Pythonic 吗?
【发布时间】:2012-10-22 13:25:53
【问题描述】:

以下哪个 if 语句更符合 Python 风格?

if not a and not b:
    do_something

if not ( a or b ):
    do something

它不是谓词逻辑,所以我应该使用 Python 关键字,因为它更具可读性对吗?

在后面的解决方案中比另一个更优化? (我不相信。)

有没有关于这方面的 PEP-8 指南?

两种方法的字节码(如果重要的话):

In [43]: def func1():
    if not a and not b:
        return
   ....:     
   ....:     

In [46]: def func2():
    if not(a or b):
        return
   ....:     
   ....:     

In [49]: dis.dis(func1)
  2           0 LOAD_GLOBAL              0 (a)
              3 UNARY_NOT           
              4 JUMP_IF_FALSE           13 (to 20)
              7 POP_TOP             
              8 LOAD_GLOBAL              1 (b)
             11 UNARY_NOT           
             12 JUMP_IF_FALSE            5 (to 20)
             15 POP_TOP             

  3          16 LOAD_CONST               0 (None)
             19 RETURN_VALUE        
        >>   20 POP_TOP             
             21 LOAD_CONST               0 (None)
             24 RETURN_VALUE        

In [50]: dis.dis(func2)
  2           0 LOAD_GLOBAL              0 (a)
              3 JUMP_IF_TRUE             4 (to 10)
              6 POP_TOP             
              7 LOAD_GLOBAL              1 (b)
        >>   10 JUMP_IF_TRUE             5 (to 18)
             13 POP_TOP             

  3          14 LOAD_CONST               0 (None)
             17 RETURN_VALUE        
        >>   18 POP_TOP             
             19 LOAD_CONST               0 (None)
             22 RETURN_VALUE        

【问题讨论】:

  • 使用 Python 关键字是什么意思?您在这两种情况下都使用 Python 关键字。
  • 抱歉,我的意思是 not() 语法。在我的情况下,如果我使用 not(a or b) 语法,有些东西看起来会更糟。因此,我更倾向于代码的第一个 sn-p
  • 我倾向于认为'do_something'和'do something'(没有下划线)可能不同
  • 因为这是最“Pythonic”的东西,所以包含字节码似乎很奇怪......另外,ab 可能包含函数调用。

标签: python pep8 demorgans-law


【解决方案1】:

我会说哪个更容易阅读,这取决于 a 和 b 是什么。

【讨论】:

  • 我们被指示更改大量代码,因为有人认为后者更具可读性。它的 python 2.6 因此任何和所有函数都可以用于更复杂的语句,但是当比较两个项目时,这很重要。我认为第一个更容易阅读,但我没有理由说另一个不是。 . .大量代码更改和单元测试要运行!
  • 很多时候这样的东西更受欢迎;或者有时您需要遵循已有的约定。如果您正在使用共享代码库,并且有些人更喜欢其中一个,那么我会遵循约定。它使整个代码库更加连贯。
【解决方案2】:

我认为您的两个示例都具有同样的可读性,但是如果我想在可读性上“将船推出”,我会选择:

not any((a, b))

因为对我来说这读起来更像英语,因此是最 Pythonic 的。

【讨论】:

  • 嗯。 +1 让我感到惊讶——我认为我从未在我的代码中使用过这种模式,我也无法解释为什么。确实,我倾向于尽可能避免使用(()),但这里还不错。
  • 然而,这将全面评估ab,而常规布尔运算符不会。不是不使用它的理由,而是需要注意的事情。
【解决方案3】:

使用哪个?对于您正在尝试做的事情,哪个更具可读性。

至于哪个效率更高,第一个确实会额外增加一个not,因此从技术上讲效率较低,但在正常情况下您不会注意到。

【讨论】:

  • 你的意思是它在技术上高效。
  • 是的,在这个笔记本电脑屏幕上,我无法同时看到问题和答案。我修好了它。 :-)
【解决方案4】:

它们是等价的,一个是否比另一个快取决于具体情况(a 和 b 的值)。

因此,只需选择您认为最易读和/或易于理解的版本。

【讨论】:

    【解决方案5】:

    我个人喜欢 Eiffel 方法,放入 pythonic 形式

    如果 a 然后 b: 做点什么

    如果 a 和 b: 做点什么

    如果 a 为假,第一种方法与第二种方法不同。在第一种情况下它不会评估 b,在第二种情况下它会。

    或等价物是“or else”

    http://en.wikipedia.org/wiki/Short-circuit_evaluation

    和/或渴望。

    然后/否则使评估短路

    语法的好处是它读起来很好,而且不会引入新的关键字。

    【讨论】:

    • 在 Python 中,通过布尔值相加或相乘,您可以获得与“急切”运算符大致相同的效果。例如bool(a) + bool(b) 是“渴望”or(总是同时评估 ab),bool(a) * bool(b) 是“渴望”and。当然,通常的andor 短路。
    【解决方案6】:

    要使一段代码成为 Python 风格,它必须本身(可读)和在其周围环境中(一致)都令读者感到愉悦。如果没有这段代码的上下文,很难给出好的意见。

    但是,另一方面......如果我认为我是 Pythonic,我需要与我的周围环境保持一致,这似乎没有考虑上下文(例如 OP)。

    第一名。

    【讨论】: