-2

Two similar codes below result in different output. Could anyone tell me why? Many thanks!

-------Code 1--------

def get_formatted_name(first_name, last_name, middle_name = ""):
    """get formal name format"""
    if middle_name:
        full_name = first_name + " " + middle_name + " " + last_name
    else:
        full_name = first_name + " " + last_name
    return full_name.title()
musician = get_formatted_name("jimi","hooker","hendrix")
print(musician)

-------output 1--------

Jimi Hendrix Hooker

-------Code 2---------

def get_formatted_name(first_name, last_name, middle_name = ""):
    """返回整洁的姓名"""
    if middle_name == True:
        full_name = first_name + " " + middle_name + " " + last_name
    else:
        full_name = first_name + " " + last_name
    return full_name.title()
musician = get_formatted_name("jimi","hooker","hendrix")
print(musician)

------output 2--------

Jimi Hooker
MisterMiyagi
  • 44,374
  • 10
  • 104
  • 119
Jeff
  • 1
  • `if "abc":` ... is going to enter the condition. `if 'abc' == True` ... is not. – Patrick Artner Jul 28 '20 at 07:49
  • What do you expect ``first_name + " " + middle_name + " " + last_name`` to do if ``middle_name == True``? In other words, what do you expect the value of ``first_name + " " + True + " " + last_name`` to be? – MisterMiyagi Jul 28 '20 at 07:50

1 Answers1

3

The first:

if middle_name:

Checks if middle_name is Truthy - that means anything that can be interpreted as true - a positive integer, a non-empty string, True, a non-empty list etc...

if middle_name == True:

Checks if middle_name is equal in value to the object True. This has some odd consequences, so a non-empty string won't match here, but a positive integer will (because that's how its equality operator is defined). Since equality can also be user-defined, anything can happen really. To avoid ambiguity when actually you want to compare to True, use

if middle_name is True:

for this test as True is a singleton, and this way you check identity (rather then equality).

kabanus
  • 24,623
  • 6
  • 41
  • 74
  • 2
    Not true... `1 == True` and `1.0 == True` and `fractions.Fraction(1, 1) == True` and `decimal.Decimal('1') == True`... and any user-defined class that implements `__eq__` could potentially be equal to `True`, `==` is **not** identity – juanpa.arrivillaga Jul 28 '20 at 07:51
  • @juanpa.arrivillaga I have to say, I did not now that about numerics! That's counter intuitive (considering for strings this seems different to me), thanks for the lesson. – kabanus Jul 28 '20 at 07:54
  • Answer edited with this info. – kabanus Jul 28 '20 at 07:55
  • 2
    It's due to the unfortunate historical fact that there used to be no `bool` type in Python, just built-in aliases `True = 1` and `False = 0`. To keep backwards compatibility, `issubclass(bool, int)`. So, `bool` objects *are numeric integer objects*. Also, and I suppose this isn't as important, but equality is defined by the type in Python, so you could define a class `class Foo: def __eq__(self, other): return True` for example, that compares equal to anything... – juanpa.arrivillaga Jul 28 '20 at 07:56
  • @juanpa.arrivillaga Thanks, that puts things in perspective, and intersting. I did include your last point already, but thanks anyway! – kabanus Jul 28 '20 at 07:57