Skip to content

trung-hn/python-tips-and-tricks

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

35 Commits
 
 
 
 
 
 
 
 

Repository files navigation

This is a Work in Progress

What is this ?

Initially, I created this list to show my friends how cool Python is. Now, this list contains Python Tips and Tricks I learned and collected from years of solving Leetcode problems. The purpose of this list is to show you the best practices in writing Pythonic code.

This uses python >= 3.6 unless specified.

How should you read this list: I separate the list into topics. Topics appear later down in the list require understandings of topics appear earlier. Thus, it's best for you to read this list from top to bottom. At the end of some topics, I have link to examples or link to more advanced topics. You can follow the links or simply ignore those for now (because you will see them later on).

Please enjoy.

Table of Contents

Basic Tips and Tricks

Swap 2 variables

In other languages, when we want to swap 2 variables, we tend to use temp to store the value. However, in Python, there is a cleaner way to do this:

a = 10
b = 20
c = 30
a, b, c = c, a, b    # <--- all three assignments are done at the same time
print(a, b, c)

# Output:
# 30 10 20

Python Unpacking

Unpack values from a tuple or a list:

first, second, last = [10, 20, 30]
print(first, second, last)

# Output:
# 10 20 30

Nested Unpacking:

matrix = [[1, 2], ["A", "B"]]
(one, two), (three, four) = matrix
print(one, two, three, four)

# Output:
# 1 2 A B

Unpacking inside a loop:

matrix = [[1, 2], [3, 4], [5, 6]]
for val1, val2 in matrix:
    print(val1, val2)

# Output:
# 1 2
# 3 4
# 5 6

More: Python Unpacking with *

Enumerate()

When writing Python, the clean way to iterate over index and value at the same time is to use enumerate() like this:

for i, val in enumerate(["A", "B", "C"]):  # <--- this has python unpacking
    print(i, val)

# Output:
# 0 A
# 1 B
# 2 C

enumerate() accepts an optional argument where you can specify starting index of i:

for i, val in enumerate(["Monday", "Tuesday", "Wednesday"], 2):
    print(i, val)

# Output:
# 2 Monday
# 3 Tuesday
# 4 Wednesday

Example:

Quick Initilization

In Python, you can quickly create a string or a list like this:

my_str = "a" * 5
my_list = [0] * 5
print(my_str)
print(my_list)

# Output:
# aaaaa
# [0, 0, 0, 0, 0]

However, NEVER do as follows:

my_list = [[0] * 5] * 2   # <--- DO NOT DO THIS. This is shallow copy
print(my_list)

# Output:
# [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]

my_list[0][0] = 5    # <--- All inner arrays will change
print(my_list)

# Output:
# [[1, 0, 0, 0, 0], [1, 0, 0, 0, 0]] 

To initialize a matrix, the best way is here

List Comprehension

Cleaner and faster way to do for loop:

nums = [i for i in range(1, 5)]
print(nums)

# Output:
# [1, 2, 3, 4]

2 for loops.

nums = [i * j for i in range(1, 5) for j in range(10, 12)]
print(nums)

# Output:
# [10, 11, 20, 22, 30, 33, 40, 44]

# Equivalent to:
nums = []
for i in range(1, 5):
    for j in range(10, 12):
        nums.append(i * j)
print(nums)

In the example above, notice that for i is the outer loop and for j is the inner loop

2 Nested for loops:

matrix = [[i * j for j in range(10, 12)] for i in range(1, 5)]
print(matrix)

# Output:
# [[10, 11], [20, 22], [30, 33], [40, 44]]

# Equivalent to:
matrix = []
for i in range(1, 5):
    row = []
    for j in range(10, 12):
        row.append(i * j)
    matrix.append(row)
print(matrix)

In the example above, pay attention to the order of for i and for j. Although for i is the outer loop, it appears after for j in the list comprehension

Examples:

Dictionary and Set Comprehension

Dictionary also has comprehension:

my_dict = {val : i for i, val in enumerate([10, 20, 30])}
print(my_dict)

# Output:
# {10: 0, 20: 1, 30: 2}

Set also has comprehension:

nums = [1,1,1,2,2,3,3,4]
my_set = {num for num in nums}
print(my_set)

# Output:
# {1, 2, 3, 4}

You might ask why bother with Set Comprehension in this case when we could do this: set(nums). The answer is because of Conditional Comprehensions

lambda Function

lambda function or anonymous function is a different way to write function. The following 2 ways are equivalent:

# Normal function
def my_func1(x):
  return x * 2

# Lambda function
my_func2 = lambda x: x * 2

print(my_func1(1))
print(my_func2(1))

# Output:
# 2
# 2

lambda function are used a lot in Key Functions like min(), max(), sort() and Functional Programming like map(), filter(), reduce()

Key Functions

Key functions are functions that take parameter key as input. key receives a function that can be a lambda. Some key functions that appear often are min(), max(), sort(), sorted(). Here are some examples:

Find longest string in array:

array = ["a", "ab", "abc"]
print(max(array, key=len)) # Note that len() itself is a function

# Output:
# "abc"

Sort array by squared value, e.g. (-2)**2 = 4

array = [-2, 0, 1]
print(sorted(array, key=lambda x:x**2)) # Note that we use lambda function here

# Output:
# [0, 1, -2]

You can read more about this from Real Python

zip()

zip() is a clean and quick way to iterate through multiple arrays at the same time.

chars = "abc"
nums = [1, 2, 3]

for char, num in zip(chars, nums):
  print(char, num)

# Output:
# a 1
# b 2
# c 3

As you can see, char and num takes value from zip(chars, nums) which iterate through both chars and nums at once. This is particularly useful when you have to deal with multiple iterable objects. However, be mindful of arrays with different length:

nums1 = [1, 2, 3]
nums2 = [4, 5, 6]
nums3 = [7, 8, 9, 10]

for n1, n2, n3 in zip(nums1, nums2, nums3):
  print(n1, n2, n3)

# Output
# 1 4 7
# 2 5 8
# 3 6 9

There are two important things to note from the above examples:

  • zip() takes as many array as you want
  • zip() only iterates up to the shortest array

More:

Built-in Libraries

collections

defaultdict

deque

Counter

Queue

itertools

accumulate

dropwhile

takewhile

groupby

chain

zip_longest

Read this first: zip()

string

When you need to get a list of characters quickly, you can get in from string. All letters:

print(string.ascii_lowercase)
print(string.ascii_letters)

# Output:
# abcdefghijklmnopqrstuvwxyz
# abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ

Or just digits:

print(string.digits)
print(string.hexdigits)

# Output:
# 0123456789
# 0123456789abcdefABCDEF

Or just punctuation:

print(string.punctuation)

# Output:
# !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~

Example

random

heapq

bisect

Functional Programming

functools

reduce

cache

Extended Tips and Tricks

Python Unpacking with *

While unpacking, you can use * to greedy match as much as it can and return a list

first, second, *rest = [1, 2, 3, 4, 5, 6]
print(first, second, rest)

# Output:
# 1 2 [3, 4, 5, 6]
# Notice that rest is a list

first, *mid, last = [1, 2, 3, 4, 5, 6]
print(first, mid, last)

# Output:
# 1 [2, 3, 4, 5] 6

Because * is greedy (matches as much as it can), you cannot use two * in one unpack

first, *mid, *rest = [1, 2, 30, 40, 50, 60]
print(first, mid, rest)

# Output
# SyntaxError: two starred expressions in assignment

Iterate through matrix by column

Conditional Comprehensions

Conditional Comprehensions allow us to add if else statement into list/set/dict comprehensions.

if statement in List Comprehension:

nums = [i for i in range(10) if i % 2]           # <--- "if" is placed at the end 
print(nums)

# Output:
# [1, 3, 5, 7, 9]

if else statement in List Comprehension. Notice that if else is placed in the front.

nums = [i if i % 2 else 0 for i in range(10)]    # <--- "if", "else" are placed in the front
print(nums)

# Output:
# [0, 1, 0, 3, 0, 5, 0, 7, 0, 9]

Multiple Statements on 1 line

Although in Python, we don't use ; often, it can help with writing multiple lines of code on the same line like this:

for i in range(3): print(i); print("--")

# Output:
# 0
# --
# 1
# --
# 2
# --

However, as you can imagine, this can be hard to read if you overuse it. So please use it with care. I tend to only use it for variable initilization.

To Add:

About

Work in progress

Resources

Stars

Watchers

Forks