$30 off During Our Annual Pro Sale. View Details »

Best Practices & Coding Style for python

Vmeyet
February 26, 2014

Best Practices & Coding Style for python

Vmeyet

February 26, 2014
Tweet

More Decks by Vmeyet

Other Decks in Programming

Transcript

  1. Best Practices & Coding Style Python

  2. Unless explicitly silenced. In the face of ambiguity, refuse the

    temptation to guess. There should be one-- and preferably only one --obvious way to do it. Although that way may not be obvious at first unless you're Dutch. Now is better than never. Although never is often better than *right* now. If the implementation is hard to explain, it's a bad idea. If the implementation is easy to explain, it may be a good idea. Namespaces are one honking great idea -- let's do more of those! Beautiful is better than ugly. Explicit is better than implicit. Simple is better than complex. Complex is better than complicated. Flat is better than nested. Sparse is better than dense. Readability counts. Special cases aren't special enough to break the rules. Although practicality beats purity. Errors should never pass silently. >>> import this The Zen of Python by Tim Peters
  3. >>> import this The Zen of Python by Tim Peters

    Readability counts. Explicit is better than implicit. Simple is better than complex. Flat is better than nested. Sparse is better than dense. There should be one-- and preferably only one --obvious way to do it. If the implementation is hard to explain, it's a bad idea. Although practicality beats purity. (A Foolish Consistency is the Hobgoblin of Little Minds)
  4. PEP 8 (python enhancement proposal) De Facto Standard Style Guide

    for Python Code. Good rules: Never mix tab and spaces. 4 space indent. Never use import * Absolute imports on separate lines at the top One line per statement Comment shouldn’t state the obvious Spaces around operators but when indicating keyword argument Old rules: 79 characters Max per line (120 at Work4)
  5. import geolocation from django.db import models class TinderUser(models.Model): ''' Model

    for the table tinder_user in MySQL''' name = models.StringField() location = models.StringField() updated_at = models.DateTimeField(auto_now=True) created_at = models.DateTimeField(auto_now_add=True) class Meta: app_label = "default" db_table = "magic_user" DISTANCE_MAX = 2 # in kilometer def get_closest_match(self): if self.name == "Florent": return "Sorry, no match was found !" lat, lng = geolocation.get_coordinate_from_city(self.location) PEP 8
  6. Write code like a pythonista Don’t Do

  7. # assign multiple vars x_val, y_val = 2, 3 #

    swap y_val, x_val = x_val, y_val # unpacking a, b = get_tuple() a, _ = get_tuple() # use the throwaway _ t = (1, True) d = {"is_admin": True} res = my_function(*t, **d) # assign multiple vars x_val = 2 y_val = 3 # swap temp = x_val x_val = y_val y_val = temp # unpacking _all = get_tuple() a = _all[0] a = _all[1] t = (1, True) d = {"is_admin": True} res = my_function( t[0], t[1], is_admin=d["is_admin"]) Swap values & unpacking
  8. # append string # performance X31 !! result = ''.join(colors)

    # check the prefix # Use the method of the class ! if foo.startswith('bar'): return True # checking appartenance for key in d: print key if key in d: print d[key] # exception to the rule for key in d.keys(): d[str(key)] = d[key] # append string result = '' for s in colors: result += s # check the prefix if foo[:3] == 'bar': return True # checking appartenance for key in d.keys(): print key if d.has_key(key): print d[key] String & dict
  9. # Is it True ? if greeting: pass # emptiness

    of dict/list/tuples/set _list = [1, 2] if _list: pass Testing True value # Is it True ? if greeting == True: pass if greeting is True: pass # emptiness of dict/list/tuples/set _list = [1, 2] if len(_list): pass
  10. # list comprehension l = [i for i in xrange(100)]

    # dict comprehension l = {i: i*3 for i in xrange(100)} # using generator gen = (x * 3 for x in xrange(100)) _sum = 0 for el in l: _sum += el # and better using built-in _sum = sum(x * 3 for x in xrange(100)) Comprehensions & Generators # list comprehension l = [] for i in range(100): l.append(i) # dict comprehension l = {} for i in range(100): l[i] = i * 3 # using one-time list for iteration l = [] for i in range(100): l.append(i * 3) _sum = 0 for el in l: _sum += el
  11. # override built-in id = 3 filter = {} sum

    = 0 # use the built-in, Luke _all = True for item in iterable: if not item: _all = False break if _all: pass _sum = 0 for x in xrange(100): _sum += x # DON’T override built-in pk = 3 sjs_filter = {} total = 0 # use the built-in, Luke all(item for item in iterable) sum(x for x in xrange(100)) # Also use the very large range of std library that comes with python Battery included
  12. # try except try: shaky_code() except: pass # It's Better

    to Beg for Forgiveness than to Ask for Permission if user.has_permission: admin.access(user.uid) #> example django model if model.objects.filter(pk=3).first(): return model.objects.get(pk=3) else: return model.objects.create(pk=3) # try except # Let non-expected exception propagate try: shaky_code() except ShakyException as e: pass # It's Better to Beg for Forgiveness than to Ask for Permission try: admin.access(user.uid) except Unauthorized: pass #> example django model try: return model.objects.get(pk=3) except model.DoesNotExists: return model.objects.create(pk=3) Exception
  13. Readability counts Code is meant to be read in 6-month

    from now Follow PEP8 rules and surrounding coding style Use a linter (pylint/pyflakes) Plugins exists for Sublime and Vim Write idiomatic python and don’t reinvent the wheel Python comes with battery included I almost forgot Avoid global when possible Avoid computationally expensive operation behind properties Decorators might be hard to write, but are easy to understand and use afterward Use context manager to close files, and run code in context Keep in Mind Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it. —Brian W. Kernighan, co-author of The C Programming Language and the "K" in "AWK"