A Python Æsthetic
Video: http://pyvideo.org/video/1599/ Slides: http://rhodesmill.org/brandon/slides/2012-11-pyconca/
Video: http://pyvideo.org/video/1676/ Slides: http://rhodesmill.org/brandon/slides/2013-03-pycon/
Name the Ducks • Well-factored Nouns • Relentless Verbs • Sin of Synecdoche • Problem of Pluralization
Well-Factored Nouns def main():! page = 'http://twitter.com/uranusjr/'! download_page(page)
Well-Factored Nouns def main():! page = 'http://twitter.com/uranusjr/'! download_page(page)! ! def download_page(page)! ... = client.get(page)
Well-Factored Nouns def main():! page = 'http://twitter.com/uranusjr/'! download_page(page)! ! def download_page(url)! page = client.get(url)
Well-Factored Nouns def main():! page = 'http://twitter.com/uranusjr/'! download_page(page)! ! def download_page(url):! page = client.get(url)! process_page(page)! ! def process_page(page):! ... = page.content
Well-Factored Nouns def main():! page = 'http://twitter.com/uranusjr/'! download_page(page)! ! def download_page(url):! page = client.get(url)! process_page(page)! ! def process_page(response):! page = response.content
Well-Factored Nouns def main():! page = 'http://twitter.com/uranusjr/'! download_page(page)! ! def download_page(url):! page = requests.get(url)! process_page(page)! ! def process_page(response):! page = response.content
Well-Factored Nouns def main():! url = 'http://twitter.com/uranusjr/'! download_page(url)! ! def download_page(url):! response = requests.get(url)! process_page(response)! ! def process_page(response):! page = response.content
Well-Factored Nouns • Plan ahead (when you can) • Refactor often • Challenge yourself
Relentless Verbs def database():! # What does this even do?! ! def get_database():! # Gets an instance for me!! ! def create_database():! # Creates a database and returns! # it for me!
Relentless Verbs def database():! # What does this even do?! ! def get_database():! # Gets an instance for me!! ! def create_database():! # Creates a database and returns! # it for me!
Relentless Verbs document.md5()! ! ! # Probably okay! ! document.get_md5()! ! document.calculate_md5()
[P]racticality beats purity.
[P]racticality beats purity. reversed(iterable)! len(iterable)! ! ! 'a'.upper()! min(iterable)! !
Relentless Verbs • Functions act • Verbose verbs can be dropped • Practicality beats purity
Sin of Synecdoche # In medialib.py:! def fetch_songs(urls):! ...! ! # In songlib.py:! def fetch(urls):! ...
Sin of Synecdoche # The caller has their choice:! ! from songlib import fetch! fetch(...)! ! # or:! ! import songlib! songlib.fetch(...)
Sin of Synecdoche • Be obvious • Don’t repeat yourself • Let users choose
Problem of Pluralization >>> connections! [<SQLConnection at 0xb72ff4d8>,! <SQLConnection at 0xb72ff4d0>,! <SQLConnection at 0xb72ff4f0>]! ! >>> connections! {'master': <SQLConnection at 0xb72ff4d8>,! 'backup': <SQLConnection at 0xb72ff4f0>}
data datum dataset datum datum datum data data data datum datum datum datum datum datasets dataset data data data data datu data data datudata datu data datudata datu datu datu datu datu datu datu datu
Anti-Plural connection_set! connection_list! connection_dict! ! def close_all(connection_seq):! ...! ! def reset_all(connection_map):! ...
I still favor plurals And documentation is always necessary.
Problem of Pluralization • Plurals can be ambiguous • There are only so many expressions • Total anti-plural may be too much
My Problem
My Problem def user_profile(request, username):! user = request.user! if user.is_authenticated:! if user.username == username:! # Show personal page! else:! # Show public page! else:! # Show page for anonymous user
My Problem def user_profile(request, username):! user = request.user! if user.is_authenticated:! if user.username == username:! # Show personal page! else:! # Show public page! else:! # Show page for anonymous user
My Problem >>> user.is_authenticated! <bound method User.is_authenticated of <User: admin>>
My Problem def user_profile(request, username):! user = request.user! if user.is_authenticated():! if user.username == username:! # Show personal page! else:! # Show public page! else:! # Show page for anonymous user
Descriptive Boolean # is + adjective = method! user.is_authenticated()! ! ! # No!! user.is_active! ! # Clearly a noun.! user.activeness
Watch Out # is + noun = variable?! >>> user.is_staff! True! ! # But...! >>> '1'.isdigit! <built-in method isdigit of str object at 0x106fa63a0>
My Current Solution # is + anything = method! user.is_authenticated()! ! ! # WRONG! method.is_action = True! ! # Considered correct (but ugly)! method.action_flag = True! ! # Maybe use something else?! method.action_info = None
Python lacked booleans until 2.2.1 Maybe we can get away with it.
Similarly Problematic # Makes more sense being a variable! request.url! ! # Obviously needs processing. Okay.! document.md5()! ! # ???! rectangle.left! rectangle.center
No Perfect Solution # Parentheses do not matter in Ruby! user.authenticated?! ! # But things can get funky quickly! proc_obj = proc { user.authenticated? }! proc_obj.call! ! # Python can be inconvenient! user.is_authenticated()! ! # But obvious things stay obvious! func = user.is_authenticated! func()
FIRE QUESTIONS

Naming Convention in Python