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

The Python You Don’t Know

The Python You Don’t Know

“You know Python. You don’t know this Python.”

Python is highly touted as “batteries-included,” referring to the extensive features provided by the standard library, so Python programmers can pick up the tool already around, and focus straight onto the real problem.

Tzu-ping Chung

August 26, 2017
Tweet

More Decks by Tzu-ping Chung

Other Decks in Programming

Transcript

  1. The Obvious • import this • python -m json.tool •

    python -m http.server • python -m zipfile • ...
  2. pathlib • Path object • Neutral or OS-specific • Path

    & file operations • open, os, os.path • glob
  3. >>> import pathlib >>> base_dir = pathlib.Path(__file__).parent >>> base_dir /

    'data' / 'main.cfg' PosixPath('data/main.cfg') >>> conf = base_dir.joinpath('data', 'main.cfg') >>> str(conf) 'data/main.cfg' >>> str(log_dir.resolve()) '/User/uranusjr/my_project/log/project.log'
  4. >>> class Color: ... RED = 1 ... GREEN =

    2 ... BLUE = 3 >>> print(Color.RED) 1 >>> print(type(Color.RED)) <class 'int'>
  5. >>> import enum >>> class Color(enum.Enum): ... RED = 1

    ... GREEN = 2 ... BLUE = 3 >>> print(Color.RED) Color.RED >>> print(type(Color.RED)) <enum 'Color'>
  6. No Duplicate Keys >>> class Shape(enum.Enum): ... SQUARE = 'square'

    ... SQUARE = '█' Traceback (most recent call last): ... TypeError: Attempted to reuse key: 'SQUARE'
  7. Value Alias Are Fine >>> class Shape(enum.Enum): ... SQUARE =

    '█' ... RECTANGLE = '█' >>> Shape.SQUARE == Shape.RECTANGLE True
  8. Unless You Say No >>> @enum.unique ... class Shape(enum.Enum): ...

    SQUARE = '█' ... RECTANGLE = '█' Traceback (most recent call last): ... ValueError: duplicate values found in <enum 'Shape'>: SQUARE -> RECTANGLE
  9. Do Things Better • Nothing you couldn’t do • Can

    be done easier, better • More type-safety?
  10. class Emptiness: def __contains__(self, x): return False def __iter__(self): return

    iter([]) def __len__(self): return 0 emptiness = Emptiness() isinstance(emptiness, Collection) # True!
  11. class Emptiness(Collection): def __contains__(self, x): return False def __iter__(self): return

    iter([]) def __len__(self): return 0 emptiness = Emptiness() isinstance(emptiness, Collection) # True!
  12. class Emptiness(Collection): def __contains__(self, x): return False def __iter__(self): return

    iter([]) # Forgot to implement __len__ emptiness = Emptiness() # TypeError: Can't instantiate abstract class # Emptiness with abstract methods __len__
  13. with connect(server, user, password, 'tempdb') as conn: with conn.cursor(as_dict=True) as

    cursor: cursor.execute( 'SELECT * FROM persons WHERE salesrep=%s', 'John Doe' ) for row in cursor: print('ID={}, Name={}'.format( row['id'], row['name'], )) http://pymssql.org/en/stable/pymssql_examples.html
  14. Avoid Lambdas • Limited introspection • No function name (anonymousness!)

    • No local scope • Difficult to make sense in traceback
  15. Lambda Alternatives • Comprehensions go a long way • If

    you need a function, just def one • But maybe you don’t!
  16. import functools def job_callback(loop): print('Finish job in', loop) def run_app():

    ... loop.call_later(functools.partial( job_callback, loop, ))
  17. # Something like this. pair_list = [ (2, 3), (19,

    8), (42, 1), ] summed_iter = map( lambda x, y: x + y, pair_list, )
  18. import operator pair_list = [ (2, 3), (19, 8), (42,

    1), ] summed_iter = map( operator.add, pair_list, )
  19. pair_list = [ (2, 3), (19, 8), (42, 1), ]

    summed_iter = map( sum, pair_list, )
  20. import math pair_list = [ (2, 3), (19, 8), (42,

    1), ] summed_iter = map( math.sum, pair_list, )
  21. list_of_lists = [ [1, 2, 3], [4, 5, 6], [7,

    8, 9], ] joined_list = functools.reduce( lambda s, x: s + x, list_of_lists, initializer=list, )
  22. list_of_lists = [ [1, 2, 3], [4, 5, 6], [7,

    8, 9], ] joined_list = functools.reduce( operator.add, list_of_lists, initializer=list, )
  23. list_of_lists = [ [1, 2, 3], [4, 5, 6], [7,

    8, 9], ] joined_list = list( itertool.chain.from_iterable( list_of_list, ), )
  24. difflib • Generates diff — diff-ing • Restores input —

    patching • Utilities for content comparison
  25. textwrap • Break text into lines • Indent, dedent, tab

    expansion • Simple hyphenation & trimming
  26. xml.* • “Mom, I don’t need lxml!” • Generate and

    parse XML • Different parsers (e.g. expat)
  27. def s_ident(scanner, token): return token def s_operator(scanner, token): return "op%s"

    % token def s_float(scanner, token): return float(token) def s_int(scanner, token): return int(token) scanner = re.Scanner([ (r"[a-zA-Z_]\w*", s_ident), (r"\d+\.\d*", s_float), (r"\d+", s_int), (r"=|\+|-|\*|/", s_operator), (r"\s+", None), ]) print(scanner.scan("sum = 3*foo + 312.50 + bar")) # (['sum', 'op=', 3, 'op*', 'foo', 'op+', 312.5, 'op+', 'bar'], '')
  28. The sre Modules • sre_constants defines constants • sre_parse defines

    a pattern and how to parse string input into one • sre_compile provides an interface to convert a pattern list to internal format
  29. asyncore • Wait, does anyone actually still use it? •

    I don’t need to tell you about asyncio • Wait that’s built-in too
  30. urllib.request • Use Requests • No good SSL support •

    Don’t use httplib either • urllib.parse is fine
  31. xml.* • Wait didn’t you just say… • Not good

    for parsing • defusedxml • Need to beware of vulnerabilities in any case
  32. Final Words • There are more! • Read the docs

    as a novel • Read the source