president: § AppNexus Data Team member § Professional software developer since leaving CMU in '05 § Author of the book, "Writing Idiomatic Python" § Private Python/Django tutor § Reasonably well-read blogger at jeffknupp.com § Can hold breath for ten minutes* *this statement is false Writing Idiomatic Python: Towards Comprehensible and Maintainable Code
“Idiomatic" (or "Pythonic“) code is code that makes use of conventions the Python community has generally accepted as “correct” • In Python, there’s usually one and only one accepted way of doing something • Who decides what is the “accepted way”? • Could be mandated in a PEP • Usually just a natural consensus the community arrives at • If there’s more than one accepted way of doing something, one of them is usually “more accepted” than the others
some_guy is a Pep Boy.""" is_pepboy = False if some_guy == 'Manny' or some_guy == 'Moe' or some_guy == 'Jack': is_pepboy = True else: is_pepboy = False return is_pepboy Idiomatic def is_some_guy_a_pepboy(some_guy): """Return True if some_guy is a Pep Boy.""" return some_guy in ('Manny', 'Moe', 'Jack') Writing Idiomatic Python: Towards Comprehensible and Maintainable Code
is idiomatic? § Often, explicitly defined in the official Python documentation § Side Note: The official documentation (including the tutorial) is absolutely packed with useful information that no one reads § By reading code § Especially modules in standard library (err, most of the time…) § By writing code and getting feedback § Getting feedback is the important part § There is no magic idiom fairy that makes your code “Pythonic” after you’ve been writing Python for a certain amount of time § By reading “Writing Idiomatic Python” by the dashing Jeff Knupp § I would refer to this as a “shameful plug” Writing Idiomatic Python: Towards Comprehensible and Maintainable Code
understand your code? § Maintainability § How easily can others (or you) make changes to your code § Correctness. § How easily can other (or you) detect bugs by reading your code? Writing Idiomatic Python: Towards Comprehensible and Maintainable Code *I don't care what language you program in; if there's some magic way of writing code that increases readability, maintainability, and correctness, take notice.
know what the code is doing without needing to think § BEWARE: Readability != Concision § Would be like measuring value of software in LOC § Easy to write impossible to understand one-liners § Primary gauge of code readability: the amount of cognitive burden it puts on the reader § Obligatory Knuth quote: Writing Idiomatic Python: Towards Comprehensible and Maintainable Code “Instead of imagining that our main task is to instruct a computer what to do, let us concentrate rather on explaining to human beings what we want a computer to do”
to Python. They're what sets Python apart from other languages. If you are learning Python coming from Java, you could write Python as if it were Java. You’d save a lot of typing (pun intended) and your code would work just fine. But it wouldn't be Pythonic. It would be some Python/Java mess (which I'd call Jython if the name weren't taken). Writing Idiomatic Python: Towards Comprehensible and Maintainable Code
your code will be a violent psychopath who knows where you live.” Writing Idiomatic Python: Towards Comprehensible and Maintainable Code --John Woods, comp.lang.c++
correctness of your code is irrelevant § Idiomatic code always makes the author's intention clear § May not actually work, but at least we know what he/she was going for… § Bad but working code is not a victimless crime… Writing Idiomatic Python: Towards Comprehensible and Maintainable Code
Towards Comprehensible and Maintainable Code index = 0 while index < len(my_list): do_something_with(my_list[index]) index += 1 I instantly become suspicious. "Why didn't she just say `for element in my_list`? Is there some subtle trick I'm missing? Let me read it again just in case." The suspicion gives way to paranoia, and eventually you've reduced me to a quivering ball of mush because you don't know the accepted way to iterate over a list in Python.
Towards Comprehensible and Maintainable Code def calculate_mean(tests):! """Return the mean score of a series of tests"""! return sum([test for test in tests]) / len(tests) 3 Factors Working Together: • Naming • Documentation • Code itself
find mistakes § The same can not be said for humans’ ability to find mistakes § Logically: § If (It is clear what you are trying to do) AND (how you do it is clear) THEN (It is easier for others to detect flaws in your thinking) Writing Idiomatic Python: Towards Comprehensible and Maintainable Code
large burden on the reader: § How likely am I, as a reader, to spot a bug? § How likely it it that I will give your review the amount of attention understanding your code would require? § How likely am I to care about reviews of your code in the future? Reading and writing code are two sides of the same coin § If you didn’t bother to write it in a clear way, why should I bother to spend the extra effort required to read it? § You are the most frequent reader of the code you write § I guarantee everyone has done the following before: 1. Come back to code you wrote previously 2. Have no recollection of how the code works or why it was done that way 3. Furiously wish to slap past version of yourself in the mouth Writing Idiomatic Python: Towards Comprehensible and Maintainable Code
a list in Python, reviewing code would be a nightmare § When you write non-idiomatic code, you’re essentially writing “for x in xs” in a different (and almost certainly, worse) way. You’re also much more likely to get that piece of code wrong § If you write code in an idiomatic fashion, small logic errors become glaringly obvious to experienced programmers reading the code § Reviewers of idiomatic code can focus on what the code does rather than how § “How” has already been established by the community § “What” is the whole point of writing a program in the first place Writing Idiomatic Python: Towards Comprehensible and Maintainable Code
for element in my_container: print ('{} {}'.format(index, element)) index += 1 Idiomatic my_container = ['Larry', 'Moe', 'Curly'] for index, element in enumerate(my_container): print ('{} {}'.format(index, element)) Writing Idiomatic Python: Towards Comprehensible and Maintainable Code
name = values[1] age = values[2] print('{name} the {animal} is {age} years old'.format( animal=animal, name=name, age=age)) Idiomatic values = ['dog', 'Fido', 10] animal, name, age = values print('{name} the {animal} is {age} years old'.format( animal=animal, name=name, age=age)) Writing Idiomatic Python: Towards Comprehensible and Maintainable Code
config_dict: if config_dict['ENABLE_LOGGING'] != True: return None elif not 'DEFAULT_LOG_LEVEL' in config_dict: return None else: return config_dict['DEFAULT_LOG_LEVEL'] else: return None Idiomatic def get_log_level(config_dict): try: if config_dict['ENABLE_LOGGING']: return config_dict['DEFAULT_LOG_LEVEL'] except KeyError: # if either value wasn't present, a KeyError will be # raised, so return None return None Writing Idiomatic Python: Towards Comprehensible and Maintainable Code
= False print ('Checking {}'.format(user)) for email_address in user.get_all_email_addresses(): if email_is_malformed(email_address): has_malformed_email_address = True print ('Has a malformed email address!') break if not has_malformed_email_address: print ('All email addresses are valid!') Idiomatic for user in get_all_users(): print ('Checking {}'.format(user)) for email_address in user.get_all_email_addresses(): if email_is_malformed(email_address): print ('Has a malformed email address!') break else: print ('All email addresses are valid!') Writing Idiomatic Python: Towards Comprehensible and Maintainable Code
code § Since realized testing and documentation are just as important § So are things like file layout, project layout, and appropriate use of source control tools § Turns out that “Writing Idiomatic Python” goes beyond simply “writing Python” Writing Idiomatic Python: Towards Comprehensible and Maintainable Code
i.e. there is such a thing as idiomatic Django § not to be confused with “idiotic Django,” which is probably written just as frequently § Some packages/projects with their own idioms § Django (duh) § Flask § SQLAlchemy § Numpy § Pandas § Requests § BeautifulSoup Writing Idiomatic Python: Towards Comprehensible and Maintainable Code
@jeffknupp § Reddit, Hacker News, and Stack Overflow § jknupp § Blog at www.jeffknupp.com § Thanks for enduring a lot of bad jokes Writing Idiomatic Python: Towards Comprehensible and Maintainable Code