My favorite Python tricks

I was recently helping a friend who was transitioning from Matlab to Python. Giving him some tips, I realized that many of the cool nuances I learned in Python were taught me by someone in a “do you know that?” style or to solve a very specific problem that could be solved more simply.

When helping this friend who is there on the other side of the world, I remembered the time when there was no one to teach me a cool trick and, in fact, I didn’t even know it could exist.

So I decided to write my favorite tricks that often make the code in much simpler and more readable way but that took me forever to figure it out. This text will be between a cheatsheet and a post and I hope it will be useful.

Exchanging values between variables

Now, imagine that we have two variables and we want to invert their values. I want the variable a to have the b value and vice versa. We can use the following logic:

a, b = 10, 5

a, b = b, a

Getting information from a dictionary

Dictionaries are wonderful structures. Now, let’s imagine that you will receive a dictionary and you are not sure if a certain key will be in the dictionary. How are you going to do that?

If we try to search for a key that does not exist, we will get a return of KeyError. A first intuitive way, would be to use a try. Example:

my_dict = {'Maria': '1235'}

try:
    value = my_dict['John'] 
except KeyError:
    value = None

It seems a lot for something so simple, right? Well, dictionaries have a method called get that will search for a key an can return None is that key doesn’t exist:

value = my_dict.get('John')

And better yet! If you another value other than None, you can define it as the second parameter of the method:

value = my_dict.get('John', 123)

# if John doesn't exist:
>>> value
123

Complicated conditionals?

Another thing that happened to me was to have a lot of if statements to do verification. My code would become long and not readable at all.

Something like this:

if my_object.my_model.value['key'] == 'something' and my_object.my_model.value['another_key'] == 23 and ... :
    pass

You get the idea… a lot of characters for some verification. Take for instance the scenario where we have 4 variables that should be checked by an if. The code would look like this:

a, b, c, d = 1, 2, 3, 4

if a == 1 and b == 2 and c == 3 and d == 4:
    print('all True!')

In this case, we want all condition to be true. Each == will return either True or False and it will only enter the block if everything is true.

First let’s take all the comparisons and add them to a list:

conditions = [
    a==1, 
    b==2, 
    c==3, 
    d==4
]

Wonderful! Now lets use the amazing function all to check if all conditions are true:

if all(conditions):
    print('all True!')

Done! Much simpler and more readable than the previous example!

Cool, right?

Now if we require that at least 1 is true (but not all), we can use the function any:

if any(conditions):
    print('at least one was true!')

Why do we need an ‘else’?

This is one of my favorites! Let’s take the function change_value that receives a value and check if it is equal to a. If true, returns 0 else it returns 1.

def change_value(x):
    if x == 'a':
        return 0
    else:
        return 1

In this case, the else becomes completely unnecessary. That’s because if anything that doesn’t fit the condition should return 1. We can simplify it to:

def change_value(x):
    if x == 'a':
        return 0
    return 1

One-line loops

Now, I want to talk about list comprehensions that I am lovingly calling one-line loops. That is one somewhat complex concept, so I’m not going to bring a long exposure on all the possibilities that exists. I want you just visualize that this is possible and often useful, ok?

Let’s go to an initial example. We have a list of integers and we would like to create a new list that contains the squared values. What we can do is create a new list (modified_list), iterate over each item in the first list and add squared value to the new list. The result is exactly what we would like:

my_list = [1, 2, 3]

modified_list = []
for x in my_list:
    modified_list.append(x**2)

# modified_list
[1, 4, 9]    

See that we “spent” 3 lines on a relatively simple problem. With list comprehension, we put the for inside the new list:

my_list = [1, 2, 3]

modified_list = [x**2 for x in my_list]

# modified_list
[1, 4, 9]    

What we basically did was to take each element in my list and make it squared. By doing this within a new list, we automatically say that the new square item should be inserted in this new list. Simple and “economical”. Of course there are multiple ways to do this and enhance the use of this method, but you understand the general idea, I hope!

One-line function

In the same way that we can do loops in one line, we can also create functions in one line. In Python, we will use lambda for this. However, make no mistake! This concept, for me, was very difficult to understand and even today I have a hard time using lambda when things start to get complicated. Again, this is just a general idea so you can know this exists.

I will try to explain why using lambda in a practical example. Imagine the following scenario: we have a list of items and we want to transform these items into values of 0 or 1.

my_list = ['a', 'b', 'b', 'c', 'a', 'b']

modified_list = [0, 1, 1, 1, 0, 1]

We can create a function that will receive the list and change the values to 0 or 1 dependinng on the item. It would look like this:

def change_value(my_list):
    modified_list = []
    for x in my_list:
        if x == 'a':
            modified_list.append(0)
        else:
            modified_list.append(1)

Let’s take the loop out of the function list. The function will only be responsible for returning the value 0 or 1 depending on the item value.

def change_value(x):
    if x == 'a':
        return 0
    return 1
            
modified_list = []
for x in my_list:
    modified_list.append(change_value(x))

Cool, our function is simple enough. Similar to what we did with list comprehensions we can represent this function the following way:

transform = lambda x: 0 if x == 'a' else 1

# type(transform)
>>> function

That is, when receiving an x, return 0 if it is equal to a or 1 in any other case. This can be used, for instance, when passing a function to a map, which will apply that function to each item in the list. That loop with several append ends up like this:

transformed_list = list(map(transform, my_list))

# transformed_list
>>> [0, 1, 1, 1, 0, 1]

Loops also have ‘else’!

One of the things that surprised me the most when I learned, was the fact that loops also have else. There are 3 cases that I will use to exemplify the use:

1. Passing an empty list

When we pass an empty list for the loop, nothing will happen, but the else is called:

my_list = []

for x in my_list:
    print('inside loop')
else:
    print('inside else')
    
# result
'inside else'

2. When the loop happens normally

When the loop receives a list that has items, it will run normally and just when all the list is finished is when the else is executed.

for x in my_list:
    print('inside loop')
else:
    print('inside else')

# result
'inside loop'
'inside loop'
'inside else'

3. Avoiding the ‘else’

If we add a break inside the loop, the loop will be interrupted and the o else will not be executed.

for x in my_list:
    print('inside loop')
    break
else:
    print('inside else')

# result
'inside loop'

String comprehension?

Strings work very similar to lists. That’s because strings are actually lists of characters. So if we do a iteration by a string, the return will be each character.

word = 'hello'

for i in word:
    print(i)
    
# result
h
e
l
l
o

Considering this, we can do something similar to what we saw in list comprehension but using string instead! For instance, let’s assume that you have a string that contains punctuation, and you want to remove them. Using this simple idea, we can do:

phrase = 'What? I don't wan't more pontucations! Enough!'

no_punctuation = ''.join(char for char in phrase if char not in [ '!', '?'])

The difference between the list comprehension and this “string comprehension” is that the first we need to add the loop inside the [] while this requires an empty string and the join method. But pretty cool, right?

Checking types

If we want to check the type of any variable we can use the function type:

>>> type('hello')
str

So it would be natural to think that we can check if a variable is of certain type using something like:

type('hello') == str

But there is a more appropriate method to do this, which is the isinstance :

isinstance('hello', str):

Simple and elegant!

Adios!

That’s it for today! I hope you enjoyed it and I hope to make new posts as I learn more “tricks”!


Cheers!
Leticia

Comments