Follow Your Gut!

But not this time…

--

I only recently learnt how to code in Python. Or should I say to code at all? I still consider myself a Python newbie, and I even doubt I will ever fully master it when I see how many things I learn every time I code. But on the other hand, that is what makes it fun, and I find it very motivating!

Throughout the last year, I have encountered a few cases with results I was not expecting. Sometimes, I clearly did not know how Python processes things under the hood and made a mistake, other times I thought I understood how things were going under the hood but, I misunderstood, it was an error of judgment.

There is a lot of articles about “why programming is so hard to learn” or “how to think like a programmer”. Hopefully, this shortlist of code snippets with unexpected ending will drag you slightly up the learning curve and make programming a little easier next time.

Booleans

In Python, any object is Truthy, if it evaluates as True, or Falsy when it evaluates as False.

Numerical values

This means True and False can have a numerical value (it is a subclass of integers after all): True = 1 and False = 0. It makes sense (everything in computers is either 1 or 0, is it not) and it probably will not impact 99% of your code, but bear that in mind when counting elements.

>>> print(f"False = {False * 4}\nTrue = {True * 3}") False = 0
True = 3

Empty vs. Non-Empty

An empty sequence is considered False whilst a non-empty one is True. It makes perfect sense to me, and I find the truthiness of objects quite useful. For example:

>>> d = {} 
>>> d == True
False>>> if d: # Instead of `if d == True:`
... print('not empty')
... else:
... print('empty')
empty

With this in mind, let us look at the following:

>>> lt = ['', 'item']
>>> lf = []

Let us check for membership now:

>>> print(f"lt = {'' in lt}\nlf = {'' in lf}\n[] == [''] = {[] == ['']}")lt = True
lf = False
[] == [''] = False

Put this way, it does make sense because the check is on the value '' and, I am sure if there were a way to represent "nothing", the interpreter would return True. But it is worth keeping in mind that Python is quite literal about what empty is.

Another example of this would be using the all() and any() functions:

>>> d = {} 
>>> print(f"d == True: {d == True}\nall(d): {all(d)}\nany(d): {any(d)}")
d == True: False
all(d): True
any(d): False
>>> d = {''}
>>> print(f"d == True: {d == True}\nall(d): {all(d)}\nany(d): {any(d)}")
d == True: False
all(d): False
any(d): False

In both cases, the dictionary evaluates to False. In the first case, it does not have any "Falsy" element so all() returns True but any(), checking for at least one truthy element, returns False. In the second case, it explicitly contains an empty element.

Once again, the correct way to see this is there are two ways for a sequence to be empty: by being empty ([] case) or by containing empty ([''] case).

Strings

Automatic Concatenation

Somehow, if you put two strings on the same line of code, the interpreter will concatenate them:

>>> 'Hello' 'World'
'HelloWorld'

In the same spirit, creating a list of letters can be quick and easy when using list().

>>> list('Hello World')
['H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd']

split()

This method will split a string on a specific character. By default, it will split the string on the space character. However:

>>> print('          Hello    '.split(' ')) 
['', '', '', '', '', '', '', '', '', '', 'Hello', '', '', '', '']
>>> print(' Hello World '.split())
['Hello', 'World']
>>> print(''.split(' '))
['']
>>> print('aaa'.split('a'))
['', '', '', '']
  • When split() is given the whitespace character to use to split the string, it splits the string on every occurrence of this whitespace.
  • When the whitespace is implicit, split() processes the string before splitting it. It cuts off the leading and trailing whitespaces and compresses the remaining whitespaces. After turning the multiple whitespaces into a single occurrence, it is used as a marker to split the string.
  • If the string is empty, split() returns an empty list.
  • When split() is given a string containing only the character to split the string with, it returns a list that is +1 longer than the initial string.

Integers

Special Cases

infinity is infinity, but not a number is not not a number.

>>> float('inf') == float('inf')
True
>>> float('NaN') == float('NaN')
False

Pre-allocation

Numbers -5 to 256 are allocated when the interpreter starts.

>>> a = 256
>>> b = 256
>>> a is b
True
>>> a = 257
>>> b = 257
>>> a is b
False
>>> a, b = 257, 257
>>> a is b
True

After these examples, it is worth reminding:

is checks the identity of objects. Whilst == checks for the equality of objects

  • In the first example, 256 is allocated when the interpreter starts. This 256 object is then referenced as a, then b but it is the same object being referenced as two different variables.
  • In the second example, 257 is created when assigned to a, then another 257 is assigned to b. We are dealing with two different 257 objects.
  • The last case shows that object allocation is done at the same time when put on the same line. The object 257 is created once then assigned to a and b.

Instinctively we expect these statements to be True because we see the values are the same. Instinctively we think a == b. Using is in this case was a mistake.

By the way, multiple assignments are considered best practice:

# Don't use temporary variables when it is not necessary
>>> def fibonacci(n):
>>> x = 0
>>> y = 1
>>> for i in range(n):
>>> print(x)
>>> t = y
>>> y = x + y
>>> x = t

# Multi assignment saves the day
>>> def fibonacci(n):
>>> x, y = 0, 1
>>> for i in range(n):
>>> print(x)
>>> x, y = y, x + y

Have a look at my previous article for more tips about code readability, best practice, and other pythonisms:

Tuples

>>> t = 'item',
>>> type(t)
tuple
>>> t = ('item' 'other_item')
>>> print(t)
itemother_item

Unlike lists and dictionaries, defined by their respective brackets, a tuple is defined by its comma, not its parenthesis.

L0lz !!1

If you have enjoyed this article and your brain does not hurt enough, head to WTF python for more Python fun! (I am not affiliated)

--

--