Skip to content

Instantly share code, notes, and snippets.

@Julynx
Last active September 19, 2024 18:46
Show Gist options
  • Save Julynx/dd500d8ae7e335c3c84684ede2293e1f to your computer and use it in GitHub Desktop.
Save Julynx/dd500d8ae7e335c3c84684ede2293e1f to your computer and use it in GitHub Desktop.
15 Python Tips To Take Your Code To The Next Level!


Basic Tips - Intermediate Tips - Advanced Tips

Basic Tips

1) Learn how to iterate properly

  • Use for index, item in enumerate(list): to loop over the index of an item and the item at the same time.
  • Use for key, value in dictn.items(): instead of iterating over keys and then getting values as dictn[key].
  • Use for item1, item2 in zip(list1, list2): to iterate over two lists at a time.

2) Use with statements to automatically close files

Instead of calling close() manually when you finish accessing a file, consider using a with statement. It's shorter, more readable, and less error-prone, as it will take care of closing the file automatically for you.

Instead of doing this... try this:
file = open(file_path, 'w')
file.write('Hello, World!')
file.close()                                   
with open(file_path, 'w') as file:
    file.write('Hello, World!')
# The file is closed automatically.             

3) Use f-strings for formatting

An f-string is preceded by the letter f and allows for inserting variables between curly braces {}. Using f-strings is generally faster and makes your code more readable.

Instead of doing this... try this:
name = input('Enter your name: ')
surname = input('Enter your surname: ')
                                               
print('Hello, ' + name + ' ' + surname)
name = input('Enter your name: ')
surname = input('Enter your surname: ')
                                                
print(f'Hello, {name} {surname}')

4) Learn to use split() and join()

If you want to separate a string into a list of substrings, use lst = text.split(separator). Use text = separator.join(lst) to merge a list of strings together.

Instead of doing this... try this:
names = ['Olivia', 'Nicholas', 'Violet']
text = ''
                                               
for name in names:
    text += name + ', '

text = text[:-2]

print(text)
>> 'Olivia, Nicholas, Violet'
names = ['Olivia', 'Nicholas', 'Violet']
text = ', '.join(names)
 
                                                
 
 
 
 
print(text)
>> 'Olivia, Nicholas, Violet' 

5) Transform list into set to remove duplicates

Instead of iterating over a list to remove duplicate elements, take advantage of the properties of certain data structures, like the set, which can only contain distinct elements.

Transform your list into a set to remove duplicate elements. You can transform it back to a list afterwards if you need to.

Instead of doing this... try this:
cities = ['London', 'Paris', 'London']
unique_cities = [] 
                                               
for city in cities: 
    if city not in unique_cities:
        unique_cities.append(city)

print(unique_cities)
>> ['London', 'Paris'] 
cities = ['London', 'Paris', 'London']
unique_cities = list(set(cities))
  
  
  
  
                                                
print(unique_cities)
>> ['London', 'Paris']

Intermediate Tips

1) Instead of if variable == a or variable == b use if variable in (a, b)

Instead of repeating a variable in different conditions of an if statement, check for belonging against a tuple of allowed values. This is shorter, less prone to error, and makes it easier to add or remove allowed values in the future.

You can also use if min <= variable <= max or if variable in range(min, max + 1) to check if a variable is within a range.

Instead of doing this... try this:
if variable == a or variable == b:
    res = do_something(variable)               
if variable in (a, b):
    res = do_something(variable)                

2) Learn how to unpack tuples

You probably already know you can unpack tuples like this first = tuple[0] and second = tuple[1].

But did you know you can also do first, second = tuple?

If the tuple has more than two elements, you can use first, second, *rest = tuple to unpack the first two elements and assign the rest to a list called rest.

Instead of doing this... try this:
runners = 'John Mike Greg Luke Bob'
positions = runners.split(' ')
 
first = positions[0]
second = positions[1]                          
rest = positions[2:]
 
  
 
runners = 'John Mike Greg Luke Bob'
first, second, *rest = runners.split(' ')  
                                                
print(first)  
>> 'John' 
print(second)
>> 'Mike'
print(rest)
>> ['Greg', 'Luke', 'Bob']  

3) Split long and difficult to read statements into multiple lines

You can encase a statement in parentheses () and split it into multiple lines.

This is useful for long statements that are difficult to read.

Instead of doing this... try this:
...                                            
return Popen(...).stdout.read().decode()...
 
 
 
 
...                                            
return (Popen(cmd, shell=True, stdout=PIPE)     
        .stdout
        .read()
        .decode()
        .strip())

4) Instead of asking for permission, ask for forgiveness

In Python, it's much more common to try: to do something and catch all possible exceptions, than to control input and output values using if statements.

More likely than not, the function already does the necessary value checks from the inside and raises all possible errors. The only thing left for you to do is to catch them and define what should happen in case of error inside an except Exception: clause.

This is why, instead of checking if a file exists and if you have permissions before opening it, you should just try to open it.

Instead of doing this... try this:
if not os.path.isfile(filename):
    print('File does not exist.')
                                               
if not os.access(filename, os.W_OK):
    print('You dont have write permission.')

with open(filename, 'w') as file:
    file.write('Hello, World!')
 
 
 
 
try:
    with open(filename, 'w') as file:
        file.write('Hello, World!')
                                                
except FileNotFoundError:
    print('File does not exist.')

except PermissionError:
    print('You dont have write permission.')

except OSError as exc:
    print(f'An OSError has occurred:\n{exc}')

5) Use center to center strings and os.get_terminal_size().columns to center to terminal.

Learn how to use text.ljust(length) to align text to the left, filling it with spaces until it reaches a desired length. Use text.rjust(length) or text.center(length) to align text to the right or center respectively. Set length = os.get_terminal_size().columns to center text relative to your terminal's width.

Instead of doing this... try this:
text = 'Hello, World'
length = 20
                                               
text = ' '*((length//2) - (len(text)//2)) \
     + text \
     + ' '*((length//2) - (len(text)//2))

print(text)
>> '    Hello, World    '
text = 'Hello, World'
length = 20

text = text.center(length)
  
 
                                                
print(text)
>> '    Hello, World    '                   

Advanced Tips

1) Learn to transform for loops into comprehensions

It's usually better to use comprehensions over for loops in Python when possible, as they are usually faster and shorter. However, it can be difficult to transform long and complex for loops into comprehensions.

If you are iterating over items, processing them in some way, and appending the results to a list to return it afterwards, try doing this instead:

First, extract the body of the loop to a separate function that processes one item at a time. Let's call it process_item(). Then, build your list comprehension by calling process_item() over all the items.

Instead of doing this... try this:
items = [item1, item2, item3, item4...]
new_items = []
                                               
for item in items:
    item = do_something(item)  # Extract
    item = do_smth_else(item)  # this
    ...                        # logic.
    new_items.append(item)
 
 
items = [item1, item2, item3, item4...]
                                               
def process_item(item):        # 'process_item'
    item = do_something(item)  #  now does the
    item = do_smth_else(item)  #  processing
    ...                        #  for a single
    return item                #  item.
                                                
new_items = [process_item(item) 
             for item in items]

2) Write readable comprehensions

List, set, dictionary, and generator comprehensions may generally be shorter and run faster, but they can also be much harder to read. This is why, instead of writing your comprehensions in a single line, try splitting them into multiple lines.

Notice how each keyword (for, in, if...) starts a new line. This makes the comprehension more comfortable to both read and modify if you need to add new conditions in the future.

Instead of doing this...
comments = {line_idx: line.strip() for line_idx, line in enumerate(file) if line.startswith('#')}     
try this:
comments = {line_idx: line.strip()    
            for line_idx, line
            in enumerate(file)
            if line.startswith('#')}                                                                  

3) Don't iterate if you don't have to

Iterating is expensive in Python and most common operations that require iteration can be done through functions that are either built-in or available in popular libraries/modules like functools, itertools, and numpy. The underlying code for these functions is usually written in C and they are highly optimized. Use them whenever possible and iterate only when strictly necessary.

Instead of doing this... try this:
numbers = [1, 3, 4, 5, 7, 9, 2]
total = 0
                                               
for number in numbers:
    total += number

avg = total / len(numbers)
numbers = [1, 3, 4, 5, 7, 9, 2]

avg = sum(numbers) / len(numbers)               
 
 
 
 

4) Use multiprocessing.Pool and get easy speedups with multiple processes

Your processor has multiple cores that can execute several tasks at the same time, but by default your code usually runs on a single core.

However, Python provides an easy way to make use of multiple processes to achieve parallelism and speedups that can go from x4 to x16 and even more for some machines.

Instead of doing this... try this:
requests = [req1, req2...]
results = []

for request in requests:
    res = process_request(request)
    results.append(res)
                                               
# Runs in 1m 22s, depending on HW.
from multiprocessing import Pool

requests = [req1, req2...]

with Pool as p:
    results = p.map(process_request, requests)
                                                
# Runs in 16s, depending on HW.

5) Use next(item for item in items if [condition]) to get the first item that matches a condition

It's a common task to get the first element of a list that has some specific property. The next() function can help you do that.

Instead of doing this... try this:
numbers = [1, 3, 4, 5, 7, 9, 2]
result = None

for number in numbers:
    if number > 3:
        result = number
        break
                                               

print(result)
>> 4 
numbers = [1, 3, 4, 5, 7, 9, 2]
result = next((number 
               for number in numbers 
               if number > 3), 
              None)  # Fallback value.
                                                
  
  
  
print(result)
>> 4
@horstjens
Copy link

very good written and clean layout, thank you for sharing!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment