[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Python-Dev] Subtle difference between f-strings and str.format()

On Fri, Mar 30, 2018 at 4:41 AM, Nick Coghlan <ncoghlan at gmail.com> wrote:
> On 30 March 2018 at 21:16, Nathaniel Smith <njs at pobox.com> wrote:
>> And bool(obj) does always return True or False; if you define a
>> __bool__ method that returns something else then bool rejects it and
>> raises TypeError. So bool(bool(obj)) is already indistinguishable from
>> bool(obj).
>> However, the naive implementation of 'if a and True:' doesn't call
>> bool(bool(a)), it calls bool(a) twice, and this *is* distinguishable
>> by user code, at least in principle.
> For example:
>     >>> class FlipFlop:
>     ...     _state = False
>     ...     def __bool__(self):
>     ...         result = self._state
>     ...         self._state = not result
>     ...         return result
>     ...
>     >>> toggle = FlipFlop()
>     >>> bool(toggle)
>     False
>     >>> bool(toggle)
>     True
>     >>> bool(toggle)
>     False
>     >>> bool(toggle) and bool(toggle)
>     False
>     >>> toggle and toggle
>     <__main__.FlipFlop object at 0x7f35293604e0>
>     >>> bool(toggle and toggle)
>     True
> So the general principle is that __bool__ implementations shouldn't do
> anything that will change the result of the next call to __bool__, or
> else weirdness is going to result.

I don't think this way of stating it is general enough. For example,
you could have a nondeterministic implementation of __bool__ that
doesn't itself carry any state (e.g. flipping the result with some
probability), but the next call could nevertheless still return a
different result. So I think Nathaniel's way of stating it is probably

> If we want to change the language spec, I guess it would be with text
> like: "if bool(obj) would be called twice in immediate succession,
> with no other code in between, then the interpreter may assume that
> both calls would return the same value and elide one of them".