*args and **kwargs
def func1(arg1, arg2, arg3): # you need to pass all args for this func
print(arg1, arg2, arg3)
def func2(arg1=None, arg2=None, arg3=None): # you don't need to pass all args for this func
print(arg1, arg2, arg3)
args = [1, 2, 3]
kwargs = {'arg2': 2, 'arg1': 1, 'arg3': 3}
func1(*args) # *args unpacks the args collection and passes the values
# Outputs: 1 2 3
func1(**kwargs) # **kwargs unpacks the args dict and passes the values to arguments matching the keys. Similar to doing *kwargs.values() but keys determine which value is passed to which argument.
# Outputs: 1 2 3
func1(*kwargs.values()) # single * doesn't match the keys to arguments
# Outputs: 2 1 3
# **kwargs makes your function very flexible:
def func3(**kwargs):
print(kwargs)
func3(**kwargs)
# Outputs: {'arg2': 2, 'arg1': 1, 'arg3': 3}
# **kwargs makes your function very flexible:
def func3(**kwargs):
print(kwargs)
func3(**kwargs)
# Outputs: {'arg2': 2, 'arg1': 1, 'arg3': 3}
Combine lists with zip()
names = ['jim', 'joe', 'bill']
ages = [32, 25, 19]
occupation = ['doctor', 'dentist', 'student']
print(list(zip(names, ages, occupation))) # zip() returns an object
# Outputs: [('jim', 32, 'doctor'), ('joe', 25, 'dentist'), ('bill', 19, 'student')]
# Where it's useful:
for name, age in zip(names, ages):
if age > 30:
print(name)
# Outputs: jim
For Else and While Else
search = [1, 2, 3, 4, 5, 6, 7]
target = 8
for element in search:
if element == target:
print('Found it!')
break
else: # if the loop was done w/o breaking
print('Didn\'t find it!')
# Outputs: Didn't find it!
i = 0
while i < len(search):
element = search[i]
if element == target:
print('Found it!')
break
i += 1
else: # if the loop was done w/o breaking
print('Didn\'t find it!')
# Outputs: Didn't find it!
Inline conditions
x = 1 if 2 > 3 else 0 # else if required here
print(x)
# Outputs: 0
Unpack a collection of items and assign them to variables
tup = (1, 2, 3, 4, 5)
a, b, c, d, e = tup
print(a, b, c, d, e)
# Outputs: 1 2 3 4 5
list = [0, 2, 4, 6, 8]
a, b, c, d, e = list
print(a, b, c, d, e)
# Outputs: 0 2 4 6 8
string = "hello"
a, b, c, d, e = string
print(a, b, c, d, e)
# Outputs: h e l l o
dic = {'a': 1, 'b': 2}
a, b = dic # assigns keys
print(a, b)
# Outputs: a b
a, b = dic.values() # assigns values
print(a, b)
# Outputs: 1 2
a, b = dic.items() # assigns items
print(a, b)
# Outputs: ('a', 1) ('b', 2)
Assign multiple variables in one line
width, height = 400, 300
print (width, height)
# Outputs: 400 300
# You can swap their values:
width, height = height, width
print (width, height)
# Outputs: 300 400
Initialize a collection in one line
x = [i for i in range(10)]
print(x)
# Outputs: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
# Conditions
x = [i for i in range(10) if i % 2 == 0]
print(x)
# Outputs: [0, 2, 4, 6, 8]
# Multiple loops
x = [i*j for i in range(3) for j in range (3)]
print(x)
# Outputs: [0, 0, 0, 0, 1, 2, 0, 2, 4]
# Creating a 2D array
x = [[0 for _ in range(2)] for _ in range(3)] # if you are not going to use the iterator index, you can use _ instead
print(x)
# Outputs: [[0, 0], [0, 0], [0, 0]]
Itertools
import itertools
lst = [1, 2, 3, 4, 5]
sum_list = itertools.accumulate(lst)
print(list(sum_list))
# Outputs: [1, 3, 6, 10, 15]
lst2 = ['a', 'b', 'c', 'd', 'e']
chain_list = itertools.chain(lst, lst2) # returns an iterator object, which is more memory efficient than merging the list
print(list(chain_list)) # here we did create a merge list for printing but you could loop through chain_list without creating a new list
# Outputs: [1, 2, 3, 4, 5, 'a', 'b', 'c', 'd', 'e']
show = [1, 0, 1, 0, 1]
compressed_list = itertools.compress(lst, show)
print(list(compressed_list))
# Outputs: [1, 3, 5]