Wednesday, July 11, 2012

IDKTAP #3: Backticks

Did you know that quoting an expression using backticks is an alias for repr() in Python 2.x? That is, it prints the "representation" of the result of the expression, which is generally what you'd have to paste into your Python source file to produce that same object.

print `"Think, it ain't illegal yet!"`

They took this out in Python 3.

Thursday, July 5, 2012

IDKTAP #2: Booleans as fancy integers

I Didn't Know That About Python uncovers surprising tidbits about our favorite programming language. 

In Python, a Boolean (type bool) is a subtype of integers. True is equal to 1 and False is equal to 0.

True  == 1   # True
False == 0   # True

The special methods called __str__ and __repr__ define how an object is converted to a string and how it is represented in an interactive context, respectively. So bool is basically implemented like this:

class bool(int):
    def __str__(self):
        return "True" if self else "False"
    __repr__ = __str__


True, False = bool(1), bool(0)

(There are some other details I'm glossing over, such as the fact that True and False are singletons and only ever have one instance. That is, bool(1) is always the same object. The example above does not have this behavior. For a fun exercise, try adding it.)

The surprising thing is that in Python 2, True and False are simply built-in identifiers assigned to two specific bool singletons. This means that they can be reassigned:

True = 3

This will very likely cause quite odd behavior in your programs, which is why Python 3 reserves True and False as actual language keywords and doesn't let you reassign them. Still, issubclass(bool, int) remains True.

Sunday, July 1, 2012

PF #2: And and/or or

Second in the Python Foundations series.

In the previous installment of Python Foundations, I described the informal nature of truth and falsity in Python (dubbed "truthy" and "falsy"). Now let's explore how the Boolean operators and and or interact with such values.

In many languages, you'd expect the result of a Boolean operation (an operation between two truth values) to be True or False. But since Python considers a wide range of values True and False in a Boolean context, it is useful to return one of the operands. That is, when you combine two values using and or or, you get one of the values you put in.

In Python, and and or are short-circuiting. They always evaluate their first operand, and if that result is sufficient to decide the truth value of the expression, they stop and don't evaluate their second operand. Say what?

OK, have a look at the truth table for and:

AND   | True   False
-----------------------
True  | True   False

False | False  False

As you can see, False and anything is always False. Therefore, when the first operand of and is falsy, Python need not evaluate the second operand, and in fact does not. This not only saves time, it can be exploited for useful side effects (more on that later).

OR    | True   False
-----------------------
True  | True   True

False | True   False

This truth table for or similarly reveals that when the first operand is True, the result is always True, so Python doesn't need to evaluate the second operand of or when the first operand is truthy. And once again, since it doesn't need to, it doesn't.

What does it mean to not evaluate the second operand of and or or?  Among other things it means that if the second operand is a function call, that second function is never called:

v = a() or b()

If a() returns something truthy, b() is never even called. But what is the value of v? Python assigns v the return value of the operand that decided the result: a() if a's return value is truthy, or b() if a's return value is falsy. It works similarly with and, except the result is a's return value if it is falsy and b's otherwise. In short, the actual operand values are used in place of the constants True and False.

Short-circuiting lets you use and and or as substitutes for if statements in certain circumstances. It's very easy to write unreadable code using short-circuiting and and or; there was an idiom that was commonly used in an attempt to make up for the fact that Python didn't have a proper ternary conditional operator. Then Python added a proper ternary conditional operator (v = a if b else c) and everybody forgot about the hackish workaround. But simpler uses of short-circuiting are pretty readable and useful.

For example, easily provide a default value for blank inputs:

name = raw_input("What is your name? ") or "Jude"
print "Hey,", name, "don't make it bad"

Or check to make sure something is callable before calling it:

callable(func) and func()

I find those generally more readable than the alternatives using if statements:

name = raw_input("What is your name? ")
if not name:
    name = "Jude"

if callable(func):
    func()

Short-circuiting is, by the way, the reason Python doesn't let you override and and or using special methods on your own objects the way you can with arithmetic operators. Both operands would be evaluated before the operation is performed, so short-circuiting simply isn't possible. (There is in fact a proposal to change that, but it hasn't been implemented yet.)