26 Pythonic Code Tips and Tricks
26 Pythonic Code Tips and Tricks
Michael Kennedy
@mkennedy
Write Pythonic Code Like a Seasoned Developer | Tips and Tricks from the Talk Python Training Course
Take the full video course at Talk Python
https://talkpython.fm/pythonic
What is Pythonic code?
Write Pythonic Code Like a Seasoned Developer | Tips and Tricks from the Talk Python Training Course
Truthiness
Write Pythonic Code Like a Seasoned Developer | Tips and Tricks from the Talk Python Training Course
Testing for None
accounts = find_accounts(search_text)
Write Pythonic Code Like a Seasoned Developer | Tips and Tricks from the Talk Python Training Course
Multiple tests against a single variable
class Moves(Enum): West=1; East=2; ...
Write Pythonic Code Like a Seasoned Developer | Tips and Tricks from the Talk Python Training Course
String formatting
name = 'Michael'
age = 43
# Pythonic
print("Hi, I'm {} and I'm {} years old.".format(name, age))
# Prints: Hi, I'm Michael and I'm 43 years old.
print("Hi, I'm {1} years old and my name is {0}, yeah {1} years.".format(name, age))
# Prints: Hi, I'm 43 years old and my name is Michael, yeah 43 years.
format_drive()
print("Format completed successful.")
sys.exit(0)
Write Pythonic Code Like a Seasoned Developer | Tips and Tricks from the Talk Python Training Course
Flat is better than nested
def download():
print("Let's try to download a file")
if not s.check_download_url():
print("Bad url")
return
if not s.check_network():
print("No network")
return
if not s.check_dns():
print("No DNS")
return
if not s.check_access_allowed():
print("No access")
return
# BAD
import sys, os, multiprocessing
from statistics import *
# GOOD
import sys
import os
import multiprocessing
# ALSO GOOD
from os import path, chmod, chown
# module data_access
Constants are UPPERCASE
# constant, not changed at runtime
TRANSCATION_MODE = 'serializable'
def __init__(self):
self.db = create_db()
Variables and args are lowercase
self.mode = 'dev'
Py3
Write Pythonic Code Like a Seasoned Developer | Tips and Tricks from the Talk Python Training Course
Adding iteration to custom types
class ShoppingCart:
def __init__(self):
self.items = []
def __iter__(self):
for it in sorted(self.items, key=lambda i: i.price):
yield it
cart = ShoppingCart()
cart.add_item(CartItem("guitar", 799))
cart.add_item(CartItem("cd", 19))
cart.add_item(CartItem("iPhone", 699))
if 2 in nums_dict:
word_version = nums_dict[2] # safe!
Write Pythonic Code Like a Seasoned Developer | Tips and Tricks from the Talk Python Training Course
On demand computation with yield
def fibonacci_generator():
current, nxt = 0, 1
while True:
current, nxt = nxt, nxt + current
yield current
Write Pythonic Code Like a Seasoned Developer | Tips and Tricks from the Talk Python Training Course
Recursive yields made easy
def get_files(folder):
for item in os.listdir(folder):
full_item = os.path.join(folder, item)
if os.path.isfile(full_item):
yield full_item
elif os.path.isdir(full_item):
yield from get_files(full_item)
Py3
Write Pythonic Code Like a Seasoned Developer | Tips and Tricks from the Talk Python Training Course
Inline generators via expressions
# direct loop style
high_measurements = []
for m in measurements:
if m.value >= 70:
high_measurements.append(m.value)
# generator style
high_measurements = (
m.value
for m in measurements
if m.value >= 70
)
Write Pythonic Code Like a Seasoned Developer | Tips and Tricks from the Talk Python Training Course
Lambda expressions
def find_special_numbers(special_selector, limit=10):
found = []
n = 0
while len(found) < limit:
if special_selector(n):
found.append(n)
n += 1
return found
find_special_numbers(lambda x: x % 6 == 0)
Write Pythonic Code Like a Seasoned Developer | Tips and Tricks from the Talk Python Training Course
Passing variable number of arguments
def biggest(x, y): *NAME signals variable length arguments [0, …)
if x > y: args is the conventional name for this argument
return x
else:
return y
return b
Write Pythonic Code Like a Seasoned Developer | Tips and Tricks from the Talk Python Training Course
Mutable values as method defaults
Default value is created once per process.
Write Pythonic Code Like a Seasoned Developer | Tips and Tricks from the Talk Python Training Course
Mutable values as method defaults
List value is created as needed.
# program.py
import support
if __name__ == '__main__':
print("The variable is {}".format(support.var))
# prints: The variable is A variable
Write Pythonic Code Like a Seasoned Developer | Tips and Tricks from the Talk Python Training Course
Virtual environments
> pip3 install virtualenv
> cd local_env/bin/
> . activate
class NotSoPythonicPet:
def __init__(self, name, age):
self.age = age
self.name = name
def get_name(self):
self.name_checked = True
return self.name
def get_age(self):
Almost never create new return self.age
fields outside of __init__.
Write Pythonic Code Like a Seasoned Developer | Tips and Tricks from the Talk Python Training Course
Encapsulation and data hiding
class PetSnake:
def __init__(self, name, age):
self.__age = age
self.__name = name Double _'s mean private.
self._protected = True Single _'s mean protected.
@property
def name(self):
return self.__name
@property
def age(self): py = PetSnake("Slide", 6)
a = py.age # a is 6
return self.__age
protected_v = py._protected # works with warning
direct_a = py.__age # crash:
# AttributeError: 'PetSnake' object has no attribute '__age'
Write Pythonic Code Like a Seasoned Developer | Tips and Tricks from the Talk Python Training Course
Properties (Pythonic)
class PetSnake:
def __init__(self, name, age):
self.__age = age
self.__name = name
@property
def name(self):
return self.__name
py = PetSnake("Slide", 6)
@property
def age(self):
print("She is named {} and {} years old."
return self.__age
.format(py.name, py.age
))
# prints: She is named Slide and 6 years old.
Write Pythonic Code Like a Seasoned Developer | Tips and Tricks from the Talk Python Training Course
Wait, is there a numerical for loop? [2]
More often, you need the index and the value.
Use enumerate for this.
Write Pythonic Code Like a Seasoned Developer | Tips and Tricks from the Talk Python Training Course
Named Tuples
named tuples are clearer and explicitly named
Measurement = collections.namedtuple(
'Measurement',
'temp, lat, long, quality')
temp = m[0]
temp = m.temp
quality = m.quality
print(m)
# Measurement(temp=22.5, lat=44.234,
long=19.02, quality='strong')
Getting the source code
https://github.com/mikeckennedy/write-pythonic-code-demos