30 python best practices

1. Use Python 3

2. Check for a minimum required Python version

if not sys.version_info > (2, 7):
   # berate your user for running a 10 year
   # python version
elif not sys.version_info >= (3, 5):
   # Kindly tell your user (s)he needs to upgrade
   # because you're using 3.5 features

3. Use IPython

IPython is basically an enhanced shell. It’s worth it just for the autocompletion alone, but there is much more. I like it too for all the magic commands that are built-in. Here are a few :
  • %cd — to change the current working directory
  • %edit — to open an editor and execute the code you typed in after closing the editor
  • %env — to show the current environment variables
  • %pip install [pkgs] — to install packages without leaving the interactive shell
  • %time and %timeit — to time the execution of Python code

Another useful feature is referencing the output of a previous command. In and Out are actual objects. You can use the output of the 3rd command by using Out[3].

Install IPython with:

pip3 install ipython

4. List Comprehensions

[ expression for item in list if conditional ]

A very basic example to fill a list with a sequence of numbers:

mylist = [i for i in range(10)]
print(mylist)
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

And because you can use an expression, you can also do some math:

squares = [x**2 for x in range(10)] print(squares)
# [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

Or even call an external function:

def some_function(a):
    return (a + 5) / 2
    
my_formula = [some_function(i) for i in range(10)]
print(my_formula)
# [2, 3, 3, 4, 4, 5, 5, 6, 6, 7]

And finally, you can use the ‘if’ to filter the list. In this case, we only keep the values that are dividable by 2:

filtered = [i for i in range(20) if i%2==0]
print(filtered)
# [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

5. Check memory usage of your objects

import sys

mylist = range(0, 10000)
print(sys.getsizeof(mylist))
# 48

Woah… wait… why is this huge list only 48 bytes?

It’s because the range function returns a class that only behaves like a list. A range is a lot more memory efficient than using an actual list of numbers.

You can see for yourself by using a list comprehension to create an actual list of numbers from the same range:

import sys

myreallist = [x for x in range(0, 10000)]
print(sys.getsizeof(myreallist))
# 87632

6. Return multiple values

def get_user(id):
    # fetch user from database
    # ....
    return name, birthdate

name, birthdate = get_user(4)

This is alright for a limited number of return values. But anything past 3 values should be put into a (data) class.

7. Use data classes

  • a data class requires a minimal amount of code
  • you can compare data classes because __eq__ is implemented for you
  • you can easily print a data class for debugging because __repr__ is implemented as well
  • data classes require type hints, reduced the chances of bugs

Here’s an example of a data class at work:

from dataclasses import dataclass

@dataclass
class Card:
    rank: str
    suit: str
    
card = Card("Q", "hearts")

print(card == card)
# True

print(card.rank)
# 'Q'

print(card)
Card(rank='Q', suit='hearts')

An in-depth guide can be found here.

8. In place variable swapping

a = 1
b = 2
a, b = b, a
print (a)
# 2
print (b)
# 1

9. Merging dictionaries (Python 3.5+)

dict1 = { 'a': 1, 'b': 2 }
dict2 = { 'b': 3, 'c': 4 }
merged = { **dict1, **dict2 }
print (merged)
# {'a': 1, 'b': 3, 'c': 4}

If there are overlapping keys, the keys from the first dictionary will be overwritten.

10. String to title case

mystring = "10 awesome python tricks"
print(mystring.title())
'10 Awesome Python Tricks'

11. Split a string into a list

mystring = "The quick brown fox"
mylist = mystring.split(' ')
print(mylist)
# ['The', 'quick', 'brown', 'fox']

12. Create a string from a list of strings

mylist = ['The', 'quick', 'brown', 'fox']
mystring = " ".join(mylist)
print(mystring)
# 'The quick brown fox'

If you were wondering why it’s not mylist.join(" ") — good question!

It comes down to the fact that the String.join() function can join not just lists, but any iterable. Putting it inside String prevents implementing the same functionality in multiple places.

13. Emoji

Image by Pixaline on Pixabay

This one will either impress or repulse, depending on who’s looking. On a more serious note, this can come in handy especially when analyzing social media data.

First, install the emoji module:

pip3 install emoji

With this installed, you can do as follows:

import emoji
result = emoji.emojize('Python is :thumbs_up:')
print(result)
# 'Python is 👍'

# You can also reverse this:
result = emoji.demojize('Python is 👍')
print(result)
# 'Python is :thumbs_up:'

Visit the emoji package page for more examples and documentation.

14. Slicing a list

a[start:stop:step]

Startstop and step are optional. If you don’t fill them in, they will default to:

  • 0 for start
  • the end of the string for end
  • 1 for step

Here are some examples:

# We can easily create a new list from 
# the first two elements of a list:
first_two = [1, 2, 3, 4, 5][0:2]
print(first_two)
# [1, 2]

# And if we use a step value of 2, 
# we can skip over every second number
# like this:
steps = [1, 2, 3, 4, 5][0:5:2]
print(steps)
# [1, 3, 5]

# This works on strings too. In Python,
# you can treat a string like a list of
# letters:
mystring = "abcdefdn nimt"[::2]
print(mystring)
# 'aced it'

15. Reversing strings and lists

revstring = "abcdefg"[::-1]
print(revstring)
# 'gfedcba'

revarray = [1, 2, 3, 4, 5][::-1]
print(revarray)
# [5, 4, 3, 2, 1]

16. Display kittens

pip3 install Pillow

Now download this image to a file called kittens.jpg:

Image by TheDigitalArtist on Pixabay

You can use the following code to display the image from your Python code:

from PIL import Image

im = Image.open("kittens.jpg")
im.show()
print(im.format, im.size, im.mode)
# JPEG (1920, 1357) RGB

Or you can do it right from IPython:

It’s me, looking at kittens

Pillow can do a lot more than displaying the image. It can analyze, resize, filter, enhance, morph, etcetera. See the documentation for all its features.

17. Using map()

map(function, something_iterable)

So you give it a function to execute, and something to execute on. This can be anything that’s iterable. In the examples below I’ll use a list.

def upper(s):
    return s.upper()
    
mylist = list(map(upper, ['sentence', 'fragment']))
print(mylist)
# ['SENTENCE', 'FRAGMENT']

# Convert a string representation of
# a number into a list of ints.
list_of_ints = list(map(int, "1234567")))
print(list_of_ints)
# [1, 2, 3, 4, 5, 6, 7]

Take a look at your own code and see if you can use map() instead of a loop somewhere!

18. Get unique elements from a list or string

mylist = [1, 1, 2, 3, 4, 5, 5, 5, 6, 6]
print (set(mylist))
# {1, 2, 3, 4, 5, 6}

# And since a string can be treated like a 
# list of letters, you can also get the 
# unique letters from a string this way:
print (set("aaabbbcccdddeeefff"))
# {'a', 'b', 'c', 'd', 'e', 'f'}

19. Find the most frequently occurring value

test = [1, 2, 3, 4, 2, 2, 3, 1, 4, 4, 4]
print(max(set(test), key = test.count))
# 4

Do you understand why this works? Try to figure it out for yourself before reading on.

You didn’t try, did you? I’ll tell you anyway:

  • max() will return the highest value in a list. The key argument takes a single argument function to customize the sort order, in this case, it’s test.count. The function is applied to each item on the iterable.
  • test.count is a built-in function of list. It takes an argument and will count the number of occurrences for that argument. So test.count(1) will return 2 and test.count(4) returns 4.
  • set(test) returns all the unique values from test, so {1, 2, 3, 4}

So what we do in this single line of code is take all the unique values of test, which is {1, 2, 3, 4}. Next, max will apply the list.count function to them and return the maximum value.

And no — I didn’t invent this one-liner.

20. Create a progress bar

pip3 install progress

Now you can create a progress bar with minimal effort:

from progress.bar import Bar

bar = Bar('Processing', max=20)
for i in range(20):
    # Do some work
    bar.next()
bar.finish()

The following animation demonstrates all the available progress types:

Animation by Giorgos Verigakis from progress

21. Use the _ in an interactive shell

In [1]: 3 * 3
Out[1]: 9In [2]: _ + 3
Out[2]: 12

This works in the Python shell too. In addition, the IPython shell allows you to use Out[n] to get the value of the expression In[n]. E.g., Out[1] would give us the number 9 in the example above.

22. Quickly create a web server

python3 -m http.server

This is useful if you want to share some stuff with a co-worker or want to test a simple HTML site.

23. Multi-Line Strings

I prefer the second way, which concatenates multiple lines together, allowing you to format your code nicely. The only downside is that you need to explicitly put in newlines.

s1 = """Multi line strings can be put
        between triple quotes. It's not ideal
        when formatting your code though"""

print (s1)
# Multi line strings can be put
#         between triple quotes. It's not ideal
#         when formatting your code though
        
s2 = ("You can also concatenate multiple\n" +
        "strings this way, but you'll have to\n"
        "explicitly put in the newlines")

print(s2)
# You can also concatenate multiple
# strings this way, but you'll have to
# explicitly put in the newlines

24. Ternary Operator For Conditional Assignment

[on_true] if [expression] else [on_false]

As an example:

x = "Success!" if (y == 2) else "Failed!"

25. Counting occurrences

from collections import Counter

mylist = [1, 1, 2, 3, 4, 5, 5, 5, 6, 6]
c = Counter(mylist)
print(c)
# Counter({1: 2, 2: 1, 3: 1, 4: 1, 5: 3, 6: 2})

# And it works on strings too:
print(Counter("aaaaabbbbbccccc"))
# Counter({'a': 5, 'b': 5, 'c': 5})

26. Chaining of comparison operators

x = 10

# Instead of:
if x > 5 and x < 15:
    print("Yes")
# yes

# You can also write:
if 5 < x < 15:
    print("Yes")
# Yes

27. Add some color

Screenshot by Jonathan Hartley from Colorama

With Colorama, you can add some color to your terminal.

28. Working with dates

pip3 install python-dateutil 

You can do so much cool stuff with this library. I’ll limit the examples to just this one that I found particularly useful: fuzzy parsing of dates from log files and such.

from colorama import Fore, Back, Style

print(Fore.RED + 'some red text')
print(Back.GREEN + 'and with a green background')
print(Style.DIM + 'and in dim text')
print(Style.RESET_ALL)
print('back to normal now')

Just remember: where the regular Python datetime functionality ends, python-dateutil comes in!

29. Integer division

By Torindkflt — Public Domain

In Python 2, the division operator ( / ) defaults to an integer division, unless one of the operands is a floating-point number. So you have this behavior:

# Python 2
5 / 2 = 2
5 / 2.0 = 2.5

In Python 3, the division operator defaults to a floating-point division and the // operator has become an integer division. So we get:

Python 3
5 / 2 = 2.5
5 // 2 = 2

For the complete motivation behind this change, you should read PEP-0238.

30. Charset detection with chardet

pip install chardet

You now have an extra command-line tool called chardetect, which can be used like this:

chardetect somefile.txt
somefile.txt: ascii with confidence 1.0

You can also use the library programmatically, check out the docs.

Leave a Comment