Python Idioms to help you write good code EuroPython 2015 Bilbao, - - PowerPoint PPT Presentation

python idioms
SMART_READER_LITE
LIVE PREVIEW

Python Idioms to help you write good code EuroPython 2015 Bilbao, - - PowerPoint PPT Presentation

Python Idioms to help you write good code EuroPython 2015 Bilbao, Spain Marc-Andr Lemburg (c) 2015 eGenix.com Software, Skills and Services GmbH, info@egenix.com Speaker Introduction Marc-Andr Lemburg Python since 1993/1994


slide-1
SLIDE 1

(c) 2015 eGenix.com Software, Skills and Services GmbH, info@egenix.com

Python Idioms

to help you write good code

EuroPython 2015 Bilbao, Spain Marc-André Lemburg

slide-2
SLIDE 2

2:55 (c) 2015 eGenix.com GmbH, info@egenix.com EuroPython 2015

Speaker Introduction Marc-André Lemburg

– Python since 1993/1994 – Studied Mathematics – eGenix.com GmbH – Senior Software Architect – Consultant / Trainer – Python Core Developer – Python Software Foundation – EuroPython Society – Based in Düsseldorf, Germany

slide-3
SLIDE 3

(c) 2015 eGenix.com GmbH, info@egenix.com EuroPython 2015 3:55

Python Idioms for cooking better Code Python Idioms for cooking better Code

slide-4
SLIDE 4

4:55 (c) 2015 eGenix.com GmbH, info@egenix.com EuroPython 2015

Agenda

  • Coding Conventions
  • Common Patterns in Python
  • Performance Idioms
  • Coding Idioms
  • Avoiding Gotchas
  • Tools
  • Questions
slide-5
SLIDE 5

5:55 (c) 2015 eGenix.com GmbH, info@egenix.com EuroPython 2015

Agenda

  • Coding Conventions
  • Common Patterns in Python
  • Performance Idioms
  • Coding Idioms
  • Avoiding Gotchas
  • Tools
  • Questions
slide-6
SLIDE 6

6:55 (c) 2015 eGenix.com GmbH, info@egenix.com EuroPython 2015

Python Coding Conventions: The Basics

slide-7
SLIDE 7

7:55 (c) 2015 eGenix.com GmbH, info@egenix.com EuroPython 2015

PEP 8 – Python Coding Conventions

  • Document:

http://www.python.org/dev/peps/pep-0008/

  • Many useful tips on how to write

readable Python code

  • Guideline, not law :-)
  • Can be used as basis for a

corporate Python style guide

  • Tool: pep8 package for checking

PEP 8 compliance

slide-8
SLIDE 8

8:55 (c) 2015 eGenix.com GmbH, info@egenix.com EuroPython 2015

Coding Conventions: Python Module Layout Generic Python module structure:

  • Header
  • Tools
  • Body
slide-9
SLIDE 9

9:55 (c) 2015 eGenix.com GmbH, info@egenix.com EuroPython 2015

Module Layout: Header Section

  • Module Doc String
  • Imports

– Python ones first – 3rd party modules – application modules

  • Constants

– usually simple types (strings, integers)

  • Globals

– often private to the module – used for e.g. caches, static mappings, etc.

slide-10
SLIDE 10

10:55 (c) 2015 eGenix.com GmbH, info@egenix.com EuroPython 2015

Module Layout: Tools Section

  • Exceptions

– used in the module – derived from standard exceptions – allow easily tracking origin of exceptions – often part of the module API

  • Helper Functions

– usually private to the module

slide-11
SLIDE 11

11:55 (c) 2015 eGenix.com GmbH, info@egenix.com EuroPython 2015

Module Layout: Body Section

  • Functions

– usually part of the module API

  • Classes

– usually part of the module API

  • Module execution (usually for testing or scripting)

– if __name__ == '__main__': main()

slide-12
SLIDE 12

12:55 (c) 2015 eGenix.com GmbH, info@egenix.com EuroPython 2015

Module Layout: Overview

  • Doc String
  • Imports
  • Constants & Globals
  • Exceptions
  • Helper Functions
  • Functions & Classes
  • Module execution (usually for testing or scripting)

– if __name__ == '__main__': main()

slide-13
SLIDE 13

13:55 (c) 2015 eGenix.com GmbH, info@egenix.com EuroPython 2015

Module Guidelines

  • Use descriptive names for modules

– try to name after the most important class

  • r function
  • Try not to use executable code

at the module top-level

– put all such code into functions to make the module import side-effect free – this is especially true for package __init__.py modules

  • Always use absolute imports
slide-14
SLIDE 14

14:55 (c) 2015 eGenix.com GmbH, info@egenix.com EuroPython 2015

Python Idioms We're now going to take a tour from high level to low level

slide-15
SLIDE 15

15:55 (c) 2015 eGenix.com GmbH, info@egenix.com EuroPython 2015

Agenda

  • Coding Conventions
  • Common Patterns in Python
  • Performance Idioms
  • Coding Idioms
  • Avoiding Gotchas
  • Tools
  • Questions
slide-16
SLIDE 16

16:55 (c) 2015 eGenix.com GmbH, info@egenix.com EuroPython 2015

Common Patterns in Python

  • Duck Typing

– API interface counts, not type – “When I see a bird that walks like a duck and swims like a duck and quacks like a duck, I call that bird a duck.” – James W. Riley

  • Examples:

– Python sequence API, iterator API, index API, mapping API, file API – ElementTree API for XML, Python DB-API – collections module provides ABCs

slide-17
SLIDE 17

17:55 (c) 2015 eGenix.com GmbH, info@egenix.com EuroPython 2015

Common Patterns in Python

  • Facade / Adapter

– Make an object API compatible with another object – Turn any bird into a duck – API based, not class based

  • Examples:

– StringIO module (turn strings into file-like objects) – DB-API compatible modules (adapt database C APIs to a standard Python API)

slide-18
SLIDE 18

18:55 (c) 2015 eGenix.com GmbH, info@egenix.com EuroPython 2015

Common Patterns in Python

  • Singletons

– Objects that only exist once – usually not enforced in Python (e.g. True, False are not protected in Py2, None is protected, all in Py3)

  • Examples:

– True, False, None, NotImplemented – Small integers

slide-19
SLIDE 19

19:55 (c) 2015 eGenix.com GmbH, info@egenix.com EuroPython 2015

Common Patterns in Python

  • Factories

– Build objects in multiple ways – Python only has one .__init__() method per class – use factory functions returning instances, or class methods to the same effect

  • Examples:

– mx.DateTime.DateTimeFrom() – datetime.fromtimestamp()

slide-20
SLIDE 20

20:55 (c) 2015 eGenix.com GmbH, info@egenix.com EuroPython 2015

Common Patterns in Python

  • Wrappers / Proxies

– hide / control APIs – add information / verification to APIs – decorators often create wrappers (try to avoid this)

  • Examples:

– decorators, functools.partial, weakref, mxProxy

slide-21
SLIDE 21

21:55 (c) 2015 eGenix.com GmbH, info@egenix.com EuroPython 2015

Common Patterns in Python

  • Callbacks

– functions/methods called when an event triggers – usually methods on a processing object (handler) or on a subclass (handler method) – hooks to extend / customize APIs – very common: runtime introspection for finding handlers

  • Examples:

– SAX parser, HTML parser, urllib2, threading – command line option processing – asynchronous processing

slide-22
SLIDE 22

22:55 (c) 2015 eGenix.com GmbH, info@egenix.com EuroPython 2015

Common Patterns in Python There's also a typical code evolution pattern in Python ...

slide-23
SLIDE 23

23:55 (c) 2015 eGenix.com GmbH, info@egenix.com EuroPython 2015

Code Evolution: From scripts to functions

  • Typical situation:

– Start with a script using top-level commands – Turn common script sections into functions – Pass around common parameters (e.g. context related variables) – Group functions

slide-24
SLIDE 24

24:55 (c) 2015 eGenix.com GmbH, info@egenix.com EuroPython 2015

Code Evolution: Abstracting functions to classes

  • Next level:

– Refactor function sections into methods of classes – Instantiate classes to drive the application – Provide a user interface (e.g. command line, web or GUI) – Add more input/output channels – More user customization

slide-25
SLIDE 25

25:55 (c) 2015 eGenix.com GmbH, info@egenix.com EuroPython 2015

Code Evolution: Abstracting classes into components

  • Evolution:

– Create subclasses to provide more features – Split code into modules to more clarity – Group modules in packages – Build loosely coupled components based on classes – Add packaging for better deployment – Add automated tests and builds – Enter build-test-release cycle – Enter the code refactor cycle

slide-26
SLIDE 26

26:55 (c) 2015 eGenix.com GmbH, info@egenix.com EuroPython 2015

Agenda

  • Coding Conventions
  • Common Patterns in Python
  • Performance Idioms
  • Coding Idioms
  • Avoiding Gotchas
  • Tools
  • Questions
slide-27
SLIDE 27

27:55 (c) 2015 eGenix.com GmbH, info@egenix.com EuroPython 2015

Performance Idioms … when performance matters

slide-28
SLIDE 28

28:55 (c) 2015 eGenix.com GmbH, info@egenix.com EuroPython 2015

Looping over sequences

  • Different methods possible:

– for-loop, map(), list comprehensions, generator

  • Fastest:

Use list comprehensions [op(x) for x in seq] when operating on sequences

slide-29
SLIDE 29

29:55 (c) 2015 eGenix.com GmbH, info@egenix.com EuroPython 2015

Joining strings

  • Using + (concat)

– Good when concatenating a few strings – Copies strings together

  • Using ''.join()

– Great for concatenating many strings – Copies strings, but only once

  • Using StringIO.write(), array.fromstring()
  • r %-formatting

– Much slower than the above two

Pyt hon rul es.

slide-30
SLIDE 30

30:55 (c) 2015 eGenix.com GmbH, info@egenix.com EuroPython 2015

Exceptions

  • Expensive in Python (but cheap in Python's C API)
  • Exceptions should only be used for

exceptional cases … # Not a good idea: try: fails_often() except ValueError: runs_often()

slide-31
SLIDE 31

31:55 (c) 2015 eGenix.com GmbH, info@egenix.com EuroPython 2015

More performance hints

  • Python wiki page:

– https://wiki.python.org/moin/PythonSpeed/Performance Tips

  • My talk “When performance matters...”

– http://www.egenix.com/library/presentations/PyCon-U K-2014-When-performance-matters/

  • Examples:

– localizing variables: x = global_x – localizing method lookups: m = list.append – dict.setdefault() and collections.defaultdict

slide-32
SLIDE 32

32:55 (c) 2015 eGenix.com GmbH, info@egenix.com EuroPython 2015

Agenda

  • Coding Conventions
  • Common Patterns in Python
  • Performance Idioms
  • Coding Idioms
  • Avoiding Gotchas
  • Tools
  • Questions
slide-33
SLIDE 33

33:55 (c) 2015 eGenix.com GmbH, info@egenix.com EuroPython 2015

Deeply nested if statements in loops

  • Typical situation:

for x in items: if cond1(x): do_something() if cond2(x): do_something_else()

slide-34
SLIDE 34

34:55 (c) 2015 eGenix.com GmbH, info@egenix.com EuroPython 2015

Deeply nested if statements in loops

  • Staircase Syndrom:

for x in items: if cond1(x): do_something() if cond2(x): do_something_else()

slide-35
SLIDE 35

35:55 (c) 2015 eGenix.com GmbH, info@egenix.com EuroPython 2015

Better: Use continue to avoid nesting for x in items: if not cond1(x): continue do_something() if not cond2(x): continue do_something_else()

slide-36
SLIDE 36

36:55 (c) 2015 eGenix.com GmbH, info@egenix.com EuroPython 2015

Avoiding Gotchas … mutable or not, that is the question (well, at least one of them)

slide-37
SLIDE 37

37:55 (c) 2015 eGenix.com GmbH, info@egenix.com EuroPython 2015

Avoid mutable state in module globals

  • Typical situations at module scope:

db = database.connect(…) settings = dict(verbose=1, log=False)

  • Not thread safe

… and no, thread locals are not a good idea

  • Difficult to manage

(access, resources, validations)

  • Dangerous in larger projects
slide-38
SLIDE 38

38:55 (c) 2015 eGenix.com GmbH, info@egenix.com EuroPython 2015

Better: Place mutable state in context objects

  • Keep state in context objects
  • Pass context to methods and functions

as first parameter

def read_data(context, key): ... def get_config(context): ...

  • r refactor code to use instance attributes:

class Application: def __init__(self): self.context = ApplicationContext()

slide-39
SLIDE 39

39:55 (c) 2015 eGenix.com GmbH, info@egenix.com EuroPython 2015

Function/method default parameters

  • Use only immutable types
  • For mutable types:

– fallback to None or – immutable alternatives – Add mutable defaults at the top of the function/method: def func(x, a=None): if a is None: a = [] return x(a)

slide-40
SLIDE 40

40:55 (c) 2015 eGenix.com GmbH, info@egenix.com EuroPython 2015

Class default attributes

  • Only use immutable types

– unless you really know what you're doing

  • For mutable types:

– fallback to None or – immutable alternatives – Add mutable type defaults in .__init__()

  • Document all attributes using comments:

# List of file names files = None

slide-41
SLIDE 41

41:55 (c) 2015 eGenix.com GmbH, info@egenix.com EuroPython 2015

Avoiding Gotchas … and finally, some very basic hints to to write better code

slide-42
SLIDE 42

42:55 (c) 2015 eGenix.com GmbH, info@egenix.com EuroPython 2015

Use the in operator in Python

  • Interface to the obj.__contains__() method
  • if x in some_list: …

– better than using some_list.index(x) with try-except

  • if x in some_dict: …

– better than using some_dict.has_key(x)

  • if x in some_set: …

– better than ??? (only way to test membership :-))

  • Function equivalent:

a in b = operator.contains(b, a)

slide-43
SLIDE 43

43:55 (c) 2015 eGenix.com GmbH, info@egenix.com EuroPython 2015

Boolean testing in Python

  • Boolean singletons:

True (=integer 1), False (= integer 0)

  • Use: if x: print(“x is true”)

Not: if x == True: print(“x is true”) Not: if x is True: print(“x is true”)

  • Use: if not x: print(“x is false”)

Not: if x == False: print(“x is false”) Not: if x is False: print(“x is false”)

  • Function equivalent: bool(x)
slide-44
SLIDE 44

44:55 (c) 2015 eGenix.com GmbH, info@egenix.com EuroPython 2015

Container empty testing in Python

  • Empty containers (sequences, mappings, sets) are

considered false in Python

  • Use: if container: print(“not empty”)

Not: if len(container): print(“not empty”) Not: if len(container) > 0: print(“not empty”)

slide-45
SLIDE 45

45:55 (c) 2015 eGenix.com GmbH, info@egenix.com EuroPython 2015

Commas in Python: 1-Tuples

  • Nasty in 1-tuples:

x = (1,) x = 1, note the comma ←

  • Weird errors when not intended…

>>> s = 'abc', >>> len(s) 1 >>> s[2] IndexError: tuple index out of range

slide-46
SLIDE 46

46:55 (c) 2015 eGenix.com GmbH, info@egenix.com EuroPython 2015

Commas in Python: Listings

  • Great in argument/parameter/item listings:

Python allows trailing “,” at end of listings...

d = {'a': 1, 'b': 2, # insert something new here }

even in functions/methods...

f(x, y, z, a=1, # insert more keyword args here )

slide-47
SLIDE 47

47:55 (c) 2015 eGenix.com GmbH, info@egenix.com EuroPython 2015

Agenda

  • Coding Conventions
  • Common Patterns in Python
  • Performance Idioms
  • Coding Idioms
  • Avoiding Gotchas
  • Tools
  • Questions
slide-48
SLIDE 48

48:55 (c) 2015 eGenix.com GmbH, info@egenix.com EuroPython 2015

Tools

  • The Python community has created

some really good tools to help with developing good code Let's have a look at some …

slide-49
SLIDE 49

49:55 (c) 2015 eGenix.com GmbH, info@egenix.com EuroPython 2015

Code Checking Tools

  • pylint: https://pypi.python.org/pypi/pylint/

– style/typo checking – good documentation: http://docs.pylint.org/

  • pep8: https://pypi.python.org/pypi/pep8/

– style checking – dohttps://pypi.python.org/pypi/flake8/cumentation: http://pep8.readthedocs.org/en/latest/)

  • pyflakes:https://pypi.python.org/pypi/pyflakes/

– logical checking – no documentation

slide-50
SLIDE 50

50:55 (c) 2015 eGenix.com GmbH, info@egenix.com EuroPython 2015

Code Checking Tools

  • flake8:

– combines pep8, pyflakes and a complexity checker – documentation: http://flake8.readthedocs.org/en/latest/)

  • pychecker: http://pychecker.sourceforge.net/

– note: imports modules – not maintained anymore (predates the other tools), but can still be useful

slide-51
SLIDE 51

51:55 (c) 2015 eGenix.com GmbH, info@egenix.com EuroPython 2015

Agenda

  • Coding Conventions
  • Common Patterns in Python
  • Performance Idioms
  • Coding Idioms
  • Avoiding Gotchas
  • Tools
  • Questions
slide-52
SLIDE 52

52:55 (c) 2015 eGenix.com GmbH, info@egenix.com EuroPython 2015

Questions

>>> >>> raise Que uestion

  • n()

raise Que uestion

  • n()
slide-53
SLIDE 53

53:55 (c) 2015 eGenix.com GmbH, info@egenix.com EuroPython 2015

Thank you for listening Beautiful is better than ugly.

slide-54
SLIDE 54

54:55 (c) 2015 eGenix.com GmbH, info@egenix.com EuroPython 2015

Photo References

CC BY / CC BY-SA licensed photos: Public domain clip arts:

https://www.flickr.com/photos/runlevel0/6297898421/ https://openclipart.org/detail/8879/rubber-duck https://openclipart.org/detail/215201/evolution

All other photos and images are used by permission.

slide-55
SLIDE 55

55:55 (c) 2015 eGenix.com GmbH, info@egenix.com EuroPython 2015

Contact

eGenix.com Software, Skills and Services GmbH Marc-André Lemburg Pastor-Löh-Str. 48 D-40764 Langenfeld Germany eMail: mal@egenix.com Phone: +49 211 9304112 Fax: +49 211 3005250 Web: http://www.egenix.com/