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 == TrueFalse>>> 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 asa
, thenb
but it is the same object being referenced as two different variables. - In the second example,
257
is created when assigned toa
, then another257
is assigned tob
. We are dealing with two different257
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 toa
andb
.
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)