Being "Pythonic" means that your code generally follows a set of idioms agreed upon by the broader python community.
"When a veteran Python developer calls portions of code not “Pythonic”, they usually mean that these lines of code do not follow the common guidelines and fail to express its intent in what is considered the most readable way. On some border cases, no best way has been agreed upon on how to express an intent in Python code, but these cases are rare."
Docstrings are an important way to document code and make clear to other programmers the intent and meaning behind what you're writing. We are somewhat different on the formatting, but we want it to include 1) Description, 2) Parameters, 3) Returns
def string_find(str1, str2):
""" Returns whether str2 can be found within str1
Parameters:
str1 (str): The haystack
str2 (str): The needle
Returns:
(bool): Whether or not str2 could be found in str1
"""
docstring.py
Map: creates a new array with the results of calling a provided function on every element in the calling array
def shout(string):
return string.upper() + "!!!!"
if __name__ == '__main__':
tutors = ['Simon', 'Teresa', 'Kaiqi', 'Michelle']
angry_tutors = list(map(shout, tutors))
print(angry_tutors)
map.py
Reduce: executes a reducer function (that you provide) on each member of the array resulting in a single output value
from functools import reduce
def custom_sum(first, second):
return first + second
if __name__ == '__main__':
studentMarks = [ 55, 43, 34, 23, 22, 10, 44 ]
total = reduce(lambda a, b: a + b, studentMarks)
print(total)
reduce.py
Filter: creates a new array with all elements that pass the test implemented by the provided function
from functools import reduce
if __name__ == '__main__':
marks = [ 65, 72, 81, 40, 56 ]
passing_marks = list(filter(lambda m: m >= 50, marks))
total = reduce(lambda a, b: a + b, passing_marks)
average = total/len(passing_marks)
print(average)
filter.py
from functools import reduce
if __name__ == '__main__':
marks = [ 39, 43.2, 48.6, 24, 33.6 ] # Marks out of 60
normalised_marks = map(lambda m: 100*m/60, marks)
passing_marks = list(filter(lambda m: m >= 50, normalised_marks))
total = reduce(lambda a, b: a + b, passing_marks)
average = total/len(passing_marks)
print(average)
allthree.py
You might be quite familiar with early returns:
def sqrt(num):
if num < 0:
return None
return num ** 0.5
myNum = int(input())
if sqrt(myNum) is not None:
print(sqrt(myNum))
early.py
The problems though are:
So we use exceptions. And we can make our own.
class SqrtException(Exception):
pass
def sqrt(num):
if num < 0:
raise SqrtException("Number cannot be < 0")
return num ** 0.5
try:
print(sqrt(int(input())))
except SqrtException as e:
print(e)
early.py
Being able to make tuples and destructure them is very powerful. If you don't want all tuples you can use blanks to ignore them.
import math
def convert(x, y):
return (math.sqrt(x**2 + y**2), math.degrees(math.atan2(y,x)))
if __name__ == '__main__':
print("Enter x coord: ", end='')
x = int(input())
print("Enter y coord: ", end='')
y = int(input())
mag, dir = convert(x, y)
print(mag, dir)
mag2, _ = convert(x, y)
print(mag2)
destructure.py
Sometimes we want to iterate cleanly over the values in a list, but also know what index we're up to. In these situations the enumerate built-in is useful.
tutors = ['Vivian', 'Rob', 'Rudra', 'Michelle']
for idx, name in enumerate(tutors):
print(f"{idx + 1}: {name}")
enumerate.py
Someones strings need to exist over multiple lines, there are two good approaches for this
if __name__ == '__main__':
text1 = """hi
this has lots of space
between chunks"""
text2 = (
"This is how you can break strings "
"into multiple lines "
"without needing to combine them manually"
)
print(text1)
print(text2)
multiline.py