Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Writing Idiomatic Python (Jeff Knupp)

NYC Python
February 06, 2014

Writing Idiomatic Python (Jeff Knupp)

Writing Idiomatic Python: Towards Comprehensible and Maintainable Code
Jeff Knupp (@jeffknupp)

as presented to NYC Python

NYC Python

February 06, 2014
Tweet

More Decks by NYC Python

Other Decks in Technology

Transcript

  1. Towards Comprehensible and Maintainable Code Jeff Knupp NYC Python Meetup

    February 6, 2014 [email protected], @jeffknupp Writing Idiomatic Python: Towards Comprehensible and Maintainable Code
  2. Here’s why you should vote for me for student body

    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
  3. What you’re about to see may shock you… Writing Idiomatic

    Python: Towards Comprehensible and Maintainable Code
  4. § What is this “idiomatic Python” I keep hearing so much

    about? § Benefits of writing idiomatic code § Spoiler Alert! §  Readability §  Maintainability §  Correctness §  End Spoiler Alert § Code samples § Idioms beyond the code itself Writing Idiomatic Python: Towards Comprehensible and Maintainable Code
  5. Hint: not “a dumb snake,” as my family and friends

    have suggested… Writing Idiomatic Python: Towards Comprehensible and Maintainable Code
  6. Writing Idiomatic Python: Towards Comprehensible and Maintainable Code Idiomatic Python:

    “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
  7. Harmful def  is_some_guy_a_pepboy(some_guy):          """Return  True  if

     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
  8. How do we know if a particular piece of 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
  9. Three Benefits: § Readability §  How easily can others (or you)

    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.
  10. When you write idiomatic Python, other Python programmers would instantly

    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”
  11. Python idioms are ways of writing code that are particular

    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
  12. “Always code as if the guy who ends up maintaining

    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++
  13. § If you're the only person who can read it, the

    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
  14. If I see code like this:   Writing Idiomatic Python:

    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.
  15. Quick, what does the following code do: Writing Idiomatic Python:

    Towards Comprehensible and Maintainable Code def  do_calculaLon(my_list):          """Return  the  results"""          running_total  =  0          number_of_scores  =  0          for  score  in  my_list:                  running_total  +=  score                  number_of_scores  +=  1              return  running_total  /  number_of_scores  
  16. Quick, what does the following code do: Writing Idiomatic 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
  17. More than just running nose and pylint… Writing Idiomatic Python:

    Towards Comprehensible and Maintainable Code
  18. § Regardless of how badly code is written, automated tests help

    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
  19. If your code is difficult to read and puts a

    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
  20. § If there were fifty equally acceptable ways to iterate over

    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
  21. Harmful my_container  =  ['Larry',  'Moe',  'Curly']   index  =  0

      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
  22. Harmful values  =  ['dog',  'Fido',  10]   animal  =  values[0]

      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
  23. Harmful def  get_log_level(config_dict):          if  'ENABLE_LOGGING'  in

     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
  24. Harmful for  user  in  get_all_users():          has_malformed_email_address

     =  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
  25. Not the title of a new police procedural on CBS…

    Writing Idiomatic Python: Towards Comprehensible and Maintainable Code
  26. § When I first gave this talk, focus was solely on

    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
  27. §  Python packages and frameworks also have idiomatic usages § 

    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
  28. §  Contact me §  Email: §  [email protected] §  Twitter § 

    @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