Implicit conversion to boolean in if and while statements

Discussion in 'Python' started by Andrew Berg, Jul 15, 2012.

  1. Andrew Berg

    Andrew Berg Guest

    This has probably been discussed before, but why is there an implicit
    conversion to a boolean in if and while statements?

    if not None:
    print('hi')
    prints 'hi' since bool(None) is False.

    If this was discussed in a PEP, I would like a link to it. There are so
    many PEPs, and I wouldn't know which ones to look through.

    Converting 0 and 1 to False and True seems reasonable, but I don't see
    the point in converting other arbitrary values.

    --
    CPython 3.3.0b1 | Windows NT 6.1.7601.17803
    Andrew Berg, Jul 15, 2012
    #1
    1. Advertising

  2. On Sun, 15 Jul 2012 03:34:46 -0500, Andrew Berg wrote:

    > This has probably been discussed before,


    By the hoary hosts of Hoggoth, has it ever!

    > but why is there an implicit
    > conversion to a boolean in if and while statements?


    It's nothing to do with if and while. All Python objects are duck-typed
    as bools.

    1) It's generally part of the duck-typing philosophy. If an object quacks
    like a bool, why not treat it as a bool?

    2) It's useful and convenient for short-circuit boolean expressions such
    as any(), all(), and various things like:

    for x in mylist or []:
    ...

    is better than:

    if mylist is not None:
    for x in mylist:
    ...

    3) Rather than distinguishing "true" from "false", a more useful
    dichotomy is between "something" and "nothing". Python includes a number
    of ways of spelling "nothing" of various types, such as:

    None, 0, 0.0, '', [], {}, set()

    and nearly everything else is "something".

    4) Other languages such as Ruby, Javascript, PHP, Clojure and others also
    distinguish between true-like and false-like ("truthy" and "falsey")
    values. Although some of them have made some pretty weird and arbitrary
    choices for what counts as true-like and false-like, without Python's
    general principle that "nothing" values should be false.

    (E.g. Javascript considers Boolean(false) to be a true value!!!)

    5) Prior to Python 2.2, there was no bool type and no True and False
    values. In fact, here is an impassioned plea from an educator begging
    Guido not to introduce True and False to the language, because duck-typed
    truthy/falsey values are *so much better*.

    http://groups.google.com/group/comp.lang.python/msg/2de5e1c8384c0360?hl=en

    Sadly, or happily, Python did grow True and False values, but the
    fundamental distinction between something and nothing still exists.

    (For the record, I can only think of one trap for the unwary: time
    objects are false at *exactly* midnight.)


    --
    Steven
    Steven D'Aprano, Jul 15, 2012
    #2
    1. Advertising

  3. Andrew Berg

    Ian Kelly Guest

    On Sun, Jul 15, 2012 at 4:56 AM, Steven D'Aprano
    <> wrote:
    > (For the record, I can only think of one trap for the unwary: time
    > objects are false at *exactly* midnight.)


    Ugh, that's irritating. I can't think of any scenario where I would
    ever want the semantics "if timeval (is not midnight):". This
    reinforces the point that if you only want to test whether you have
    None, you should use "is not None" rather than relying on __bool__.
    Ian Kelly, Jul 15, 2012
    #3
  4. Andrew Berg

    Rick Johnson Guest

    On Sunday, July 15, 2012 11:19:16 AM UTC-5, Ian wrote:
    > On Sun, Jul 15, 2012 at 4:56 AM, Steven D'Aprano
    > <> wrote:
    > > (For the record, I can only think of one trap for the unwary: time
    > > objects are false at *exactly* midnight.)

    >
    > Ugh, that's irritating. I can't think of any scenario where I would
    > ever want the semantics "if timeval (is not midnight):". This
    > reinforces the point that if you only want to test whether you have
    > None, you should use "is not None" rather than relying on __bool__.


    I think this issue is not so much a "bool test" vs "type test", but more anambiguous syntax issue. Consider this:

    ## EXAMPLE A ##
    py> if money:
    .... do_something()

    The syntax "if money" implies we are testing/measuring some attribute of "money", but what exactly about money are we testing/measuring? The problem lies in the syntax. To understand this syntax, we must first interpret what *IF* means, and we should *NEVER* need to interpret such a well defined word as *IF*! This syntax is far too opaque. Consider the alternative:

    ## EXAMPLE B ##
    py> if bool(money):
    .... do_something()

    Now we have a hint. Even if we don't understand the inner workings of the "bool" function, we *do* understand that the statement "bool(money)" *must* return True or the block *will not* execute.

    We must NEVER present "if" in such confusing manner as ExampleA. I believe Guido made a grave mistake allowing this syntax to flourish. His intentionswhere noble, to save people a few keystrokes, but all he accomplished was to pave a road directly into hell.

    "Explict is better than Implict"
    Rick Johnson, Jul 15, 2012
    #4
  5. Andrew Berg

    Rick Johnson Guest

    On Sunday, July 15, 2012 11:19:16 AM UTC-5, Ian wrote:
    > On Sun, Jul 15, 2012 at 4:56 AM, Steven D'Aprano
    > <> wrote:
    > > (For the record, I can only think of one trap for the unwary: time
    > > objects are false at *exactly* midnight.)

    >
    > Ugh, that's irritating. I can't think of any scenario where I would
    > ever want the semantics "if timeval (is not midnight):". This
    > reinforces the point that if you only want to test whether you have
    > None, you should use "is not None" rather than relying on __bool__.


    I think this issue is not so much a "bool test" vs "type test", but more anambiguous syntax issue. Consider this:

    ## EXAMPLE A ##
    py> if money:
    .... do_something()

    The syntax "if money" implies we are testing/measuring some attribute of "money", but what exactly about money are we testing/measuring? The problem lies in the syntax. To understand this syntax, we must first interpret what *IF* means, and we should *NEVER* need to interpret such a well defined word as *IF*! This syntax is far too opaque. Consider the alternative:

    ## EXAMPLE B ##
    py> if bool(money):
    .... do_something()

    Now we have a hint. Even if we don't understand the inner workings of the "bool" function, we *do* understand that the statement "bool(money)" *must* return True or the block *will not* execute.

    We must NEVER present "if" in such confusing manner as ExampleA. I believe Guido made a grave mistake allowing this syntax to flourish. His intentionswhere noble, to save people a few keystrokes, but all he accomplished was to pave a road directly into hell.

    "Explict is better than Implict"
    Rick Johnson, Jul 15, 2012
    #5
  6. Andrew Berg

    Andrew Berg Guest

    On 7/15/2012 5:56 AM, Steven D'Aprano wrote:
    > 3) Rather than distinguishing "true" from "false", a more useful
    > dichotomy is between "something" and "nothing". Python includes a number
    > of ways of spelling "nothing" of various types, such as:
    >
    > None, 0, 0.0, '', [], {}, set()
    >
    > and nearly everything else is "something".

    Okay, I see the value in this, but I don't understand why None has a
    truth value. I would expect None to mean "doesn't exist" or "unknown" or
    something like that - e.g., a value of 0 means 0 jelly beans in the jar
    and None means there isn't a jar.

    FWIW, I have, for a reason I forget, gotten into the habit of writing
    "if x is not None" when testing for None. However, I have not been
    writing "if x is True: ..."/"elif x is False: ..."/"else: 'ruh-roh'"
    when testing for True (in cases where a value of True or False makes
    sense, but any other value would not). Should I?

    --
    CPython 3.3.0b1 | Windows NT 6.1.7601.17803
    Andrew Berg, Jul 15, 2012
    #6
  7. Andrew Berg

    Andrew Berg Guest

    On 7/15/2012 11:19 AM, Ian Kelly wrote:
    > Ugh, that's irritating. I can't think of any scenario where I would
    > ever want the semantics "if timeval (is not midnight):".

    It's not implemented with such a test, but
    logging.handlers.TimedRotatingFileHandler has an option to rollover at
    midnight.
    --
    CPython 3.3.0b1 | Windows NT 6.1.7601.17803
    Andrew Berg, Jul 15, 2012
    #7
  8. Andrew Berg

    Ian Kelly Guest

    On Sun, Jul 15, 2012 at 11:16 AM, Andrew Berg <> wrote:
    > On 7/15/2012 11:19 AM, Ian Kelly wrote:
    >> Ugh, that's irritating. I can't think of any scenario where I would
    >> ever want the semantics "if timeval (is not midnight):".

    > It's not implemented with such a test, but
    > logging.handlers.TimedRotatingFileHandler has an option to rollover at
    > midnight.


    Nor could it be implemented with such a test, since the rollover check
    would then have to run at exactly midnight for the test to evaluate
    false. If it were off by 1 microsecond, it would miss it.
    Ian Kelly, Jul 15, 2012
    #8
  9. Andrew Berg

    Ian Kelly Guest

    On Sun, Jul 15, 2012 at 10:50 AM, Rick Johnson
    <> wrote:
    > I think this issue is not so much a "bool test" vs "type test", but more an ambiguous syntax issue. Consider this:
    >
    > ## EXAMPLE A ##
    > py> if money:
    > ... do_something()
    >
    > The syntax "if money" implies we are testing/measuring some attribute of "money", but what exactly about money are we testing/measuring? The problemlies in the syntax. To understand this syntax, we must first interpret what *IF* means, and we should *NEVER* need to interpret such a well defined word as *IF*! This syntax is far too opaque. Consider the alternative:
    >
    > ## EXAMPLE B ##
    > py> if bool(money):
    > ... do_something()
    >
    > Now we have a hint. Even if we don't understand the inner workings of the"bool" function, we *do* understand that the statement "bool(money)" *must* return True or the block *will not* execute.


    So now instead of having to understand how "if" handles arbitrary
    values, we have to understand how "bool" handles arbitrary values.
    How is that an improvement?

    What should "if" do if presented a value that isn't True or False?
    Raise a TypeError?

    Next thing we know, people get so used to wrapping everything they
    present to "if" in a "bool()" call, that they start writing silly
    things like "if bool(x == 7)" and "if bool(isinstance(x, int))". Why?
    Because it's faster and easier to automatically wrap the value in
    "bool" than it is to put in the effort to verify that the value will
    always be a bool to begin with in order to avoid a useless and
    annoying exception. At the point that happens, the "bool()" is
    effectively just part of the if syntax, and we're back to where we
    started.
    Ian Kelly, Jul 15, 2012
    #9
  10. Andrew Berg

    Rick Johnson Guest

    On Sunday, July 15, 2012 1:01:58 PM UTC-5, Ian wrote:

    > So now instead of having to understand how "if" handles arbitrary
    > values, we have to understand how "bool" handles arbitrary values.
    > How is that an improvement?


    Because we are keeping the condition consistent. We are not relying on implicit resolution of an object's value based on some dark, esoteric and inconsistent rules that defy all normal logic.

    > What should "if" do if presented a value that isn't True or False?
    > Raise a TypeError?


    YES! Because IT IS the author's responsibility to present a condition that evaluates to either True or False. Anything else would be ridiculously inconsistent.

    > Next thing we know, people get so used to wrapping everything they
    > present to "if" in a "bool()" call, that they start writing silly
    > things like "if bool(x == 7)" and "if bool(isinstance(x, int))".


    We cannot prevent morons from doing stupid things. "x==7" IS an explicit statement that evaluates to either True or False. Likewise, isinstance(obj, type) is a function that evaluates to either True or False. Wrapping either example in a bool call is redundant and only obfuscates the meaning. True equals True and False equal False. Why do you need to test that truth?

    The only time you will be forced to use the bool is when you are NOT using rich comparisons or NOT using truth testing functions in a condition. The following require NO bool function:

    obj == obj -> bool
    obj != obj -> bool
    obj > obj -> bool
    obj < obj -> bool
    obj >= obj -> bool
    obj <= obj -> bool
    isinstance(obj, type) -> bool
    callable(obj) -> bool
    hasattr(obj, name) -> bool
    issubclass(obj, name) -> bool
    ...along with any function that returns a bool

    Whereas:
    "if obj" -> Some esoteric semantics that defies all logic!

    > Why?
    > Because it's faster and easier to automatically wrap the value in
    > "bool" than it is to put in the effort to verify that the value will
    > always be a bool to begin with in order to avoid a useless and
    > annoying exception.


    No, because we want our code to be EXPLICIT and consistent! Remember, writing obfuscated code is easy, however, interpreting obfuscated code is difficult! A good measure of your programming skill is to see how easily your code is read by the majority.

    """If it's difficult to explain, it's probably a bad idea""".

    "if blah" is difficult to explain, whereas "if bool(blah)" is not.

    > At the point that happens, the "bool()" is
    > effectively just part of the if syntax, and we're back to where we
    > started.


    That's a ridiculous conclusion. See points above^^^
    Rick Johnson, Jul 15, 2012
    #10
  11. Andrew Berg

    Rick Johnson Guest

    On Sunday, July 15, 2012 1:01:58 PM UTC-5, Ian wrote:

    > So now instead of having to understand how "if" handles arbitrary
    > values, we have to understand how "bool" handles arbitrary values.
    > How is that an improvement?


    Because we are keeping the condition consistent. We are not relying on implicit resolution of an object's value based on some dark, esoteric and inconsistent rules that defy all normal logic.

    > What should "if" do if presented a value that isn't True or False?
    > Raise a TypeError?


    YES! Because IT IS the author's responsibility to present a condition that evaluates to either True or False. Anything else would be ridiculously inconsistent.

    > Next thing we know, people get so used to wrapping everything they
    > present to "if" in a "bool()" call, that they start writing silly
    > things like "if bool(x == 7)" and "if bool(isinstance(x, int))".


    We cannot prevent morons from doing stupid things. "x==7" IS an explicit statement that evaluates to either True or False. Likewise, isinstance(obj, type) is a function that evaluates to either True or False. Wrapping either example in a bool call is redundant and only obfuscates the meaning. True equals True and False equal False. Why do you need to test that truth?

    The only time you will be forced to use the bool is when you are NOT using rich comparisons or NOT using truth testing functions in a condition. The following require NO bool function:

    obj == obj -> bool
    obj != obj -> bool
    obj > obj -> bool
    obj < obj -> bool
    obj >= obj -> bool
    obj <= obj -> bool
    isinstance(obj, type) -> bool
    callable(obj) -> bool
    hasattr(obj, name) -> bool
    issubclass(obj, name) -> bool
    ...along with any function that returns a bool

    Whereas:
    "if obj" -> Some esoteric semantics that defies all logic!

    > Why?
    > Because it's faster and easier to automatically wrap the value in
    > "bool" than it is to put in the effort to verify that the value will
    > always be a bool to begin with in order to avoid a useless and
    > annoying exception.


    No, because we want our code to be EXPLICIT and consistent! Remember, writing obfuscated code is easy, however, interpreting obfuscated code is difficult! A good measure of your programming skill is to see how easily your code is read by the majority.

    """If it's difficult to explain, it's probably a bad idea""".

    "if blah" is difficult to explain, whereas "if bool(blah)" is not.

    > At the point that happens, the "bool()" is
    > effectively just part of the if syntax, and we're back to where we
    > started.


    That's a ridiculous conclusion. See points above^^^
    Rick Johnson, Jul 15, 2012
    #11
  12. Andrew Berg

    Terry Reedy Guest

    On 7/15/2012 12:19 PM, Ian Kelly wrote:
    > On Sun, Jul 15, 2012 at 4:56 AM, Steven D'Aprano
    > <> wrote:
    >> (For the record, I can only think of one trap for the unwary: time
    >> objects are false at *exactly* midnight.)

    >
    > Ugh, that's irritating. I can't think of any scenario where I would
    > ever want the semantics "if timeval (is not midnight):". This


    When printing time tables, midnight may be either 24:00 or 0:00,
    depending on whether it is the end or start of a journey. That could, of
    course, be done by explicit if time == midnight: rather than if not time:.

    Whether to change the current behavior was discussed on python-ideas a
    couple of months ago. I believe inertia and back-compatibity and the
    rare use case won.

    > reinforces the point that if you only want to test whether you have
    > None, you should use "is not None" rather than relying on __bool__.


    Right.

    --
    Terry Jan Reedy
    Terry Reedy, Jul 15, 2012
    #12
  13. Andrew Berg

    Terry Reedy Guest

    On 7/15/2012 1:02 PM, Andrew Berg wrote:
    > On 7/15/2012 5:56 AM, Steven D'Aprano wrote:
    >> 3) Rather than distinguishing "true" from "false", a more useful
    >> dichotomy is between "something" and "nothing". Python includes a number
    >> of ways of spelling "nothing" of various types, such as:
    >>
    >> None, 0, 0.0, '', [], {}, set()
    >>
    >> and nearly everything else is "something".

    > Okay, I see the value in this, but I don't understand why None has a
    > truth value.


    Because everything does (or should).

    > I would expect None to mean "doesn't exist" or "unknown" or
    > something like that - e.g., a value of 0 means 0 jelly beans in the jar
    > and None means there isn't a jar.
    >
    > FWIW, I have, for a reason I forget, gotten into the habit of writing
    > "if x is not None" when testing for None.


    If x might possibly be any other false value (as is, I think, the usual
    case), that is the right thing to do. Even if no other false value is
    possible, I would still use 'is not None' just to be clear what the
    false alternative is, and to guard against mistakes (like not knowing
    that time values can be false) or code changes that add the possibility
    of ohter false values.

    > However, I have not been
    > writing "if x is True: ..."/"elif x is False: ..."/"else: 'ruh-roh'"
    > when testing for True (in cases where a value of True or False makes
    > sense, but any other value would not). Should I?


    If you only want to execute the if branch when x is literally the bool
    object True and x could be some other non-bool true value such as 1 or
    'a' or [1], etc, then you should.

    If x is guaranteed to be True or False, which is the case you more or
    less proposed, then you should not. For instance, "if isinstance(x, int)
    is True:" or "if (n > 3) is True:" are redundant.

    --
    Terry Jan Reedy
    Terry Reedy, Jul 15, 2012
    #13
  14. On Mon, Jul 16, 2012 at 4:56 AM, Rick Johnson
    <> wrote:
    > On Sunday, July 15, 2012 1:01:58 PM UTC-5, Ian wrote:
    >
    >> So now instead of having to understand how "if" handles arbitrary
    >> values, we have to understand how "bool" handles arbitrary values.
    >> How is that an improvement?

    >
    > Because we are keeping the condition consistent. We are not relying on implicit resolution of an object's value based on some dark, esoteric and inconsistent rules that defy all normal logic.
    >
    >> What should "if" do if presented a value that isn't True or False?
    >> Raise a TypeError?

    >
    > YES! Because IT IS the author's responsibility to present a condition that evaluates to either True or False. Anything else would be ridiculously inconsistent.


    Then the construct "if bool(some_condition):" is redundant. What
    you've described is a viable system (REXX, for instance, demands that
    an IF statement be given strictly either a 1 or a 0 (there's no True
    and False values, but you're not allowed to use 527 as a True value,
    it has to be 1)), but it's still redundant to attempt the cast. For
    instance, this REXX function will logically negate a value twice, thus
    forcing it to boolean:

    bool: procedure
    return \\arg(1)

    But if it's given a non-bool, it'll just bomb, exactly the same as the
    if statement would. So Ian's point still stands.

    ChrisA
    Chris Angelico, Jul 15, 2012
    #14
  15. Andrew Berg

    Ranting Rick Guest

    On Jul 15, 4:53 pm, Chris Angelico <> wrote:
    > Then the construct "if bool(some_condition):" is redundant.


    Wrong again, pay attention Chris!

    It's ONLY redundant IF "some_condition" is a rich comparison: like
    "(a==b)" OR a boolean function: like "callable(a)".

    If HOWEVER we want to "truth test" an object (as in: "if obj") we
    should be FORCED to use the bool! Why? Because explicit is better than
    implicit and readability counts if we want to create maintainable code
    bases!

    if bool(obj) and a==b: # Correct!
    if obj and a==b: # Incorrect!

    Both lines of code currently produce the same result because
    "somebody" decided to give objects esoteric boolean values. Sure, we
    saved a few key stokes in a condition, but sadly at the cost of
    readability and consistency. I see no reason why choosing implicit
    resolution is better than explicit resolution. Saving six keystrokes
    is simply not enough!

    Python's motto has always been "readability counts", and for that
    reason, we should return to Explicit Boolean Resolution if we want to
    adhere to those principals.
    Ranting Rick, Jul 16, 2012
    #15
  16. On Mon, Jul 16, 2012 at 11:21 AM, Ranting Rick
    <> wrote:
    > If HOWEVER we want to "truth test" an object (as in: "if obj") we
    > should be FORCED to use the bool! Why? Because explicit is better than
    > implicit and readability counts if we want to create maintainable code
    > bases!
    >
    > if bool(obj) and a==b: # Correct!
    > if obj and a==b: # Incorrect!


    That still doesn't answer the question of what bool(obj) should do if
    obj is not a bool, and why if can't do the exact same thing, since if,
    by definition, is looking for a boolean state selector.

    ChrisA
    Chris Angelico, Jul 16, 2012
    #16
  17. On Sun, 15 Jul 2012 10:19:16 -0600, Ian Kelly wrote:

    > On Sun, Jul 15, 2012 at 4:56 AM, Steven D'Aprano
    > <> wrote:
    >> (For the record, I can only think of one trap for the unwary: time
    >> objects are false at *exactly* midnight.)

    >
    > Ugh, that's irritating. I can't think of any scenario where I would
    > ever want the semantics "if timeval (is not midnight):".


    Yes, it is a genuine gotcha. Time values are numbers, and zero is falsey,
    so midnight is falsey even though it shouldn't be.

    There's no good solution here, since we have a conflict between treating
    time values as time values ("midnight is nothing special") and as numbers
    ("midnight == 0 which is falsey"). The only "solution" is to throw out
    duck-typing of boolean values, which is tossing the baby out with the
    bathwater -- bool duck-typing works fine for everything else.


    > This
    > reinforces the point that if you only want to test whether you have
    > None, you should use "is not None" rather than relying on __bool__.


    Often you should, but I didn't mention anything about testing for None.
    Testing objects in a boolean context is more than just testing for None.

    I have just written a bunch of code with about two dozen examples similar
    to this:

    for item in (seq or []):
    do_something_with(item)

    iterates over seq if it is non-empty, or the empty list. Writing it like
    this would be more painful, more complex, less readable and less
    idiomatic:

    if seq is not None:
    for item in seq:
    do_something_with(item)


    not to mention completely unnecessary if you have already checked that
    seq is either None or a sequence, and not some other arbitrary value.

    (If seq really could be any type at all, then an explicit identity test
    against None is required.)


    One of my favourites:

    value = (dict or {}).get('key')

    instead of:

    value = None if dict is None else dict.get('key')



    --
    Steven
    Steven D'Aprano, Jul 16, 2012
    #17
  18. On Sun, Jul 15, 2012 at 9:51 PM, Chris Angelico <> wrote:
    >> if bool(obj) and a==b: # Correct!
    >> if obj and a==b: # Incorrect!

    >
    > That still doesn't answer the question of what bool(obj) should do if
    > obj is not a bool, and why if can't do the exact same thing, since if,
    > by definition, is looking for a boolean state selector.


    If can obviously do the exact same thing -- it does, in Python.

    I don't agree with the angle that Rick is spinning, so let me write my
    own: By forcing the objects in conditional to be booleans, you are
    forced to do something to non-booleans to convert them. By doing so,
    you will help inform the reader what the non-boolean is, which makes
    it easier for them to figure out the code.

    For example, instead of "if stack:" or "if bool(stack):", we could use
    "if stack.isempty():". This line tells us explicitly that stack is a
    container. Or instead of "if dist:" or "if bool(dist):" we could use
    "if dist == 0:". This tells us explicitly that stack is a number.
    Supposedly this makes it easier to read code. It certainly reads more
    like English! :)

    As far as I know, the only use of having a polymorphic boolean
    conversion is reducing the amount of typing we do. Generally objects
    with otherwise different interfaces are not interchangeable just
    because they can be converted to booleans, so you wouldn't lose much
    by being forced to explicitly convert to boolean with something
    interface-specific.

    -- Devin
    Devin Jeanpierre, Jul 16, 2012
    #18
  19. Andrew Berg

    Ranting Rick Guest

    On Jul 15, 8:51 pm, Chris Angelico <> wrote:
    > On Mon, Jul 16, 2012 at 11:21 AM, Ranting Rick
    >
    > <> wrote:
    > > If HOWEVER we want to "truth test" an object (as in: "if obj") we
    > > should be FORCED to use the bool! Why? Because explicit is better than
    > > implicit and readability counts if we want to create maintainable code
    > > bases!

    >
    > > if bool(obj) and a==b: # Correct!
    > > if obj and a==b:       # Incorrect!

    >
    > That still doesn't answer the question of what bool(obj) should do if
    > obj is not a bool, and why if can't do the exact same thing, since if,
    > by definition, is looking for a boolean state selector.
    >
    > ChrisA


    My point is no different than this example:

    py> cost = 1.75
    py> cost
    1.75
    py> 'Cost = ' + cost

    Traceback (most recent call last):
    File "<pyshell#17>", line 1, in <module>
    'Cost = ' + cost
    TypeError: cannot concatenate 'str' and 'float' objects
    py> 'Cost = ' + str(cost)
    'Cost = 1.75'

    We DON'T want Python to silently convert "cost" to a string. What we
    DO want is to force the author to use the str function thereby making
    the conversion explicit.

    Same with converting objects to bools.

    We DON'T want "if" to magically convert a non-boolean into a boolean.
    What we DO want is to force the author to use the bool function
    thereby making the conversion explicit. By doing so we transform
    confusion into comprehension. By doing so we maintain the principals
    of readability counts.
    Ranting Rick, Jul 16, 2012
    #19
  20. On Sun, 15 Jul 2012 12:02:37 -0500, Andrew Berg wrote:

    > On 7/15/2012 5:56 AM, Steven D'Aprano wrote:
    >> 3) Rather than distinguishing "true" from "false", a more useful
    >> dichotomy is between "something" and "nothing". Python includes a
    >> number of ways of spelling "nothing" of various types, such as:
    >>
    >> None, 0, 0.0, '', [], {}, set()
    >>
    >> and nearly everything else is "something".

    > Okay, I see the value in this, but I don't understand why None has a
    > truth value.


    And this is exactly the sort of mental confusion that Laura Crichton
    warned about (see the link I included earlier).

    Thinking about "truth values" is harmful, since that's arbitrary. That
    way goes to Javascript, PHP, Ruby etc. that seem to arbitrary pick
    whatever things are truthy or falsey according to some random whim, or
    according to some implementation detail that is meaningless outside of
    the implementation, such as Javascript insisting that while false is
    falsey, if you box it in an object it becomes truthy.

    It's crap like that which gives duck-typing bools a bad name.

    The distinction you should consider is:

    - is it something, or nothing?

    (relative to the type in question, of course)

    Python (at least the built-ins, third-party code can do any old crap they
    want) is consistent in this. Instances which represent something/non-
    emptiness are true, those which represent nothing/emptiness are false.

    0? That's the int that represents nothing, so it's false.

    23.723? That's one of many floats that represents something, so it's true.

    'spam'? That's one of many non-empty strings, so it's true.

    ''? That's an empty string, that it, it contains nothing, so it is false.

    None? That represents a lack of a thing, that is, nothing, so it's false.

    (Please don't get into a great philosophical debate over whether
    nothingness is itself something. That impressed me when I was 15. But now
    I know about reification: just because we have a name for a concept
    doesn't mean that the concept is something concrete. None is an object,
    but it *represents* the lack of an object.)


    > I would expect None to mean "doesn't exist" or "unknown" or
    > something like that - e.g., a value of 0 means 0 jelly beans in the jar
    > and None means there isn't a jar.


    How you interpret some_variable = None depends on what some_variable
    represents. If some_variable represents "number of jelly beans in a jar",
    then that should be 0 if there is no jar.

    If you want to create a language with ternary truth values (yes, no, mu)
    or some larger number (yes, no, maybe, mu, contradiction, unknowable,
    ....) be my guest. Just do everyone a favour and do some research on the
    large literature on non-boolean logic systems first.


    > FWIW, I have, for a reason I forget, gotten into the habit of writing
    > "if x is not None" when testing for None. However, I have not been
    > writing "if x is True: ..."/"elif x is False: ..."/"else: 'ruh-roh'"
    > when testing for True (in cases where a value of True or False makes
    > sense, but any other value would not). Should I?


    Only if you want people to laugh at you.

    If you *genuinely* want to implement Java in Python, then be explicit
    about your type-testing:

    if isinstance(x, bool) and x: ...

    or even

    if type(x) is bool and x: ... # disallow subclasses

    Otherwise, where do you stop?

    if x is True is True is True is True is True is ...


    Or you could just write idiomatic Python code, including duck-typing, and
    that includes duck-typing bools. Why do you care if somebody calls your
    function with flag=1 instead of flag=True?



    --
    Steven
    Steven D'Aprano, Jul 16, 2012
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. J Leonard
    Replies:
    4
    Views:
    12,664
    Mark Space
    Jan 19, 2008
  2. John Crichton
    Replies:
    6
    Views:
    259
    John Crichton
    Jul 12, 2010
  3. Metre Meter
    Replies:
    7
    Views:
    363
    Metre Meter
    Aug 6, 2010
  4. Chris Angelico
    Replies:
    0
    Views:
    196
    Chris Angelico
    Jul 15, 2012
  5. Stefan Behnel
    Replies:
    0
    Views:
    192
    Stefan Behnel
    Jul 15, 2012
Loading...

Share This Page