We started the morning off with this article.

True and False are also integers 1 and 0:

True == 1
False == 0

This means that can be used to count things with sum().

Python uses shortcutting when evaluating logical expressions, so if it already knows the answer, the other statements will never be executed.

The is operator validates the identity of an object.

The in operator validates the membership of an object.

You can chain comparisons, but sometimes the output isn’t what you would expect.

def foo():
  print("I'm foo")
  return 1

print("0 < foo() < 2", 0 < foo() < 2)
print("(0 < foo()) and (foo() < 2)", (0 < foo()) and (foo() < 2))

I'm foo
0 < foo() < 2 True
I'm foo
I'm foo
(0 < foo()) and (foo() < 2) True
a = 0
print("a is a < 1:", a is a < 1)
a is a < 1: True

Apparently this is because Python is going to break this statement down into 2 different statements:

  • a is a is True
  • a < 1 is True

And True and True is True ? I really can’t figure this rule out, usually I’d just rely on parentheses … until I found this fantastic article:

Under the Hood: Python Comparison Breakdown

When it solidified the fact that this must be how the interpreter is doing it’s job:

a = 0
print("a is a and a < 1:", a is a and a < 1)
a is a and a < 1: True

In the Repl I actually used the disassembler to see how this function gets decomposed, and it starts to make more sense. The use of JUMP_IF_FALSE_OR_POP could allow you to consider that the “join” of the two comparisons isn’t so much of an “and-ing” of the two comparisons, but simply that the first comparison is simply not false.

Anyways we go on to learn that None is a special keyword in Python to mean the “lack of value”. It’s pretty clever and evaluates to False, but does not equal False.

Functions are also always truthy, which has the odd side effect that if you forget to put parentheses at the end of the name of a function, it will silently always return True.

any() and all() are sort of like and and or except they don’t return their last value that’s been evaluated.

any() , like or, returns True if any of its arguments are truthy.

all() , like and, returns True if all of its arguments are truthy.

Lists and Tuples


  • are ordered.
  • can contain any arbitrary objects.
  • List elements can be accessed by index.
  • can be nested to arbitrary depth.
  • are mutable.
  • are dynamic.

Tuples are the same except:

  • are defined by enclosing the elements in parentheses (()) instead of square brackets ([]).
  • are immutable.
  • can be packed and unpacked.

There’s some discussion on when to use each. The consensus seems to be that you should use Tuples when you know the values inside the container aren’t going to change, and you’d like to iterate over them repeatedly. Similarly, you can use Tuples as dictionary keys, which is sorta nice because a Tuple can be a sort of composite container of information.

Repl of the Day