10 Python Tips and Tricks That Make Your Code Better

Sahil Hashimli
Star Gazers
Published in
7 min readOct 26, 2020

Python is an interpreted, object-oriented, high-level programming language with dynamic semantics. It’s high-level built-in data structures, combined with dynamic typing and dynamic binding, make it very attractive for Rapid Application Development, as well as for use as a scripting or glue language to connect existing components together.

Python is a very popular language. It’s also one of the languages that I recommend for beginners to start with. But how do you go about learning this language?

Here are some cool python tricks:

Use list comprehension:

Since Python 2.0, you can use list comprehension to replace many “for” and “while” blocks. List comprehension is faster because it is optimized for the Python interpreter to spot a predictable pattern during looping. As a bonus, list comprehension can be more readable (functional programming), and in most cases, it saves you one extra variable for counting. For example, let’s get the even numbers between 1 to 10 with one line.

Example:

# the good way to iterate a range
evens = [ i for i in range(10) if i%2 == 0]
print(evens)
Output: [0, 2, 4, 6, 8]
# the following is not so "Pythonic"
i = 0
evens = []
while i < 10:
if i %2 == 0: evens.append(i)
i += 1
print(evens)
Output: [0, 2, 4, 6, 8]

Use concatenating strings

When you need to concatenate a list of strings, you can do this using a for loop by adding each element one by one. However, this would be very inefficient, especially if the list is long. In Python, strings are immutable, and thus the left and right strings would have to be copied into the new string for every pair of concatenation.

A better approach is to use the join() function as shown below:

characters = ['p', 'y', 't', 'h', 'o', 'n']
word = "".join(characters)
print(word)
Output: python

Use enumerate function

The enumerate() method adds counter to an iterable and returns it (the enumerate object).

The syntax of enumerate() is:

enumerate(iterable, start=0)

start is optional. enumerate() starts counting from this number. If start is omitted, 0 is taken as start.

Example:

grocery = ['bread', 'milk', 'butter']

for item in enumerate(grocery):
print(item)

print('\n')
for count, item in enumerate(grocery):
print(count, item)

print('\n')
# changing default start value
for count, item in enumerate(grocery, 100):
print(count, item)
Output: (0, 'bread')
(1, 'milk')
(2, 'butter')

0 bread
1 milk
2 butter

100 bread
101 milk
102 butter

Use lambda function

In Python, an anonymous function is a function that is defined without a name. While normal functions are defined using the def keyword in Python, anonymous functions are defined using the lambda keyword.

Syntax of Lambda Function in python:

lambda arguments: expression

Example:

# The following example is not recommended in Python if function is simpledef add(x, y):
return x + y
print(add(2, 3))Output: 5# In such cases, it is advisable to use the lambda function instead of the def functionadd = lambda x, y: x + Y
print(add(2, 3))
Output: 5

Understand that a Python list is actually an array:

List in Python is not implemented as the usual single-linked list that people talk about in Computer Science. The list in Python is an array. That is, you can retrieve an element in a list using an index with constant time O(1), without searching from the beginning of the list. What’s the implication of this? A Python developer should think for a moment when using insert() on a list object. For example: >>> list.insert(0, element)

That is not efficient when inserting an element at the front, because all the subsequent index in the list will have to be changed. You can, however, append an element to the end of the list efficiently using list.append(). Pick deque, however, if you want fast insertion or removal at both ends. It is fast because the deque in Python is implemented as a double-linked list.

Use ZIP when working with lists

Suppose you were given a task to combine several lists with the same length and print out the result? Again, here is a more generic way to get the desired result by utilizing zip() as shown in the code below:

countries = ['France', 'Germany', 'Canada']
capitals = ['Paris', 'Berlin', 'Ottawa']
for country, capital in zip(countries,capitals):
print(country, capital)
Output: France Paris
Germany Berlin
Canada Ottawa

Use collections

Python collections are container data types, namely lists, sets, tuples, dictionary. The collections module provides high-performance datatypes that can enhance your code, making things much cleaner and easier. There are a lot of functions provided by the collections module. For this demonstration, I will be using Counter() function.

The Counter() function takes an iterable, such as a list or tuple, and returns a Counter Dictionary. The dictionary’s keys will be the unique elements present in the iterable, and the values for each key will be the count of the elements present in the iterable.

To create a counter object, pass an iterable (list) to Counter() function as shown in the code below.

from collections import Counter
count = Counter(['a','b','c','d','b','c','d','b'])
print(count)
Output: Counter({'b': 3, 'c': 2, 'd': 2, 'a': 1})

Use itertools

The Python itertools module is a collection of tools for handling iterators. itertools has multiple tools for generating iterable sequences of input data. Here I will be using itertools.combinations() as an example. itertools.combinations() is used for building combinations. These are also the possible groupings of the input values

from itertools import combinations
comb_list = list(combinations('12345',2))
print(comb_list)
Output: [('1', '2'), ('1', '3'), ('1', '4'), ('1', '5'), ('2', '3'), ('2', '4'), ('2', '5'), ('3', '4'), ('3', '5'), ('4', '5')]

You can read my blog for more information.

Use generators

Generators are very easy to implement, but a bit difficult to understand.

Generators are used to create iterators, but with a different approach. Generators are simple functions which return an iterable set of items, one at a time, in a special way.

When an iteration over a set of item starts using the for statement, the generator is run. Once the generator’s function code reaches a “yield” statement, the generator yields its execution back to the for loop, returning a new value from the set. The generator function can generate as many values (possibly infinite) as it wants, yielding each one in its turn.

Here is a simple example of a generator function which returns 7 random integers:

import randomdef lottery():
# returns 6 numbers between 1 and 40
for i in range(6):
yield random.randint(1, 40)
# returns a 7th number between 1 and 15
yield random.randint(1,15)
for random_number in lottery():
print(“And the next number is… %d!” %(random_number))
Output: And the next number is... 17! And the next number is... 36! And the next number is... 37! And the next number is... 15! And the next number is... 5! And the next number is... 27! And the next number is... 11!

Use decorators

Python has an interesting feature called decorators to add functionality to an existing code.

This is also called metaprogramming because a part of the program tries to modify another part of the program at compile time.

Functions and methods are called callable as they can be called.

In fact, any object which implements the special __call__() method is termed callable. So, in the most basic sense, a decorator is a callable that returns a callable.

Basically, a decorator takes in a function, adds some functionality and returns it.

def make_pretty(func):
def inner():
print("I got decorated")
func()
return inner
def ordinary():
print("I am ordinary")

When you run the following codes in shell,

>>> ordinary()
I am ordinary
>>> # let's decorate this ordinary function
>>> pretty = make_pretty(ordinary)
>>> pretty()
I got decorated
I am ordinary

In the example shown above, make_pretty() is a decorator. In the assignment step:

pretty = make_pretty(ordinary)

The function ordinary() got decorated and the returned function was given the name pretty.

We can see that the decorator function added some new functionality to the original function. This is similar to packing a gift. The decorator acts as a wrapper. The nature of the object that got decorated (actual gift inside) does not alter. But now, it looks pretty (since it got decorated).

Generally, we decorate a function and reassign it as,

ordinary = make_pretty(ordinary).

This is a common construct and for this reason, Python has a syntax to simplify this.

We can use the @ symbol along with the name of the decorator function and place it above the definition of the function to be decorated. For example,

@make_pretty
def ordinary():
print("I am ordinary")

is equivalent to

def ordinary():
print("I am ordinary")
ordinary = make_pretty(ordinary)

This is just a syntactic sugar to implement decorators.

def print_metadata(f):
def r(*args,**kwargs):
print (f.__name__ , ‘function ‘)
print (‘Arguments: ‘, args, kwargs)

Conclusions

In this article, I’ve presented 10 Python tips and tricks that make your code better and can be used as a reference in your day-to-day work. I hope you enjoyed this article.

--

--

Sahil Hashimli
Star Gazers

Writer about programming, technology and more. Co-founder and editor of Star Gazers publication.