
On Fri, Mar 30, 2018 at 1:08 AM, Chris Angelico <rosuav@gmail.com> wrote:
On Thu, Mar 29, 2018 at 11:28 PM, Steven D'Aprano <steve@pearwood.info> wrote:
On Wed, Mar 28, 2018 at 06:27:19PM +0300, Serhiy Storchaka wrote:
The optimizer already changes semantic. Non-optimized "if a and True:" would call bool(a) twice, but optimized code calls it only once.
I don't understand this. Why would bool(a) be called twice, and when did this change? Surely calling it twice would be a bug.
I just tried the oldest Python 3 I have on this computer, 3.2, and bool is only called once.
Technically not bool() itself, but the equivalent. Here's some similar code:
Wow, I'm good. Premature send much? Nice going, Chris. Let's try that again. Here's some similar code:
def f(a): ... if a and x: ... print("Yep") ... class Bool: ... def __bool__(self): ... print("True?") ... return True ... x = 1 f(Bool()) True? Yep
This is, however, boolifying a, then boolifying x separately. To bool a twice, you'd need to write this instead:
def f(a): ... if a or False: ... print("Yep") ...
In its optimized form, this still only boolifies a once. But we can defeat the optimization:
def f(a): ... cond = a or False ... if cond: ... print("Yep") ... f(Bool()) True? True? Yep
The "or False" part implies a booleanness check on its left operand, and the 'if' statement performs a boolean truthiness check on its result. That means two calls to __bool__ in the unoptimized form. But it gets optimized, on the assumption that __bool__ is a pure function. The version assigning to a temporary variable does one check before assigning, and then another check in the 'if'; the same thing without the temporary skips the second check, and just goes ahead and enters the body of the 'if'. Technically that's a semantic change. But I doubt it'll hurt anyone. ChrisA