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

The Python You Don’t Know

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.

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.

Avatar for Tzu-ping Chung

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