Python

also see Python Sucks

compiling python

New contender mypyc

Namespace Example

class Data(object):
    def __init__(self, adict):
        self.__dict__.update(adict)

test = {'animal': 'squirrel', 'foo': 'bar', 'color': 'red', 1: 2}

data = Data(test) 

dir(data) 
[1,
 '__class__',
 [...]
 '__weakref__',
 'animal',
 'color',
 'foo']

format example

>>> 'Hello {0}!'.format('Wordl')
'Hello Worldl'
>>> '{1} {0}!'.format('Hello', 'World')
'World Hello'
>>> 'Hello {name}!.format(name='World')
'Hello World'
>>> 'It\'s  {0:%H:%M}'.format(datetime.today())
'It's 09:22'

also see fstring cheat sheet

dog to cat

>>> class Animal(object):
        def __init__(self, name):
            self.name = name
        
>>> class Dog(Animal):
        def bark(self):
            print('woff-woff')
        
>>> class Cat(Animal):
        def meow(self):
            print('meoooow')
        
>>> fifi = Dog('fifi')
>>> fifi.bark()
woff-woff
>>> fifi.meow()
---> 1 fifi.meow()

AttributeError: 'Dog' object has no attribute 'meow'
>>> fifi.__class__
__main__.Dog
>>> fifi.__class__ = Cat
>>> isinstance(fifi, Cat)
True
>>> fifi.bark()
----> 1 fifi.bark()

AttributeError: 'Cat' object has no attribute 'bark'
>>> fifi.meow()
meoooow
>>> fifi.name
'fifi'
AttributeError: 'Dog' object has no attribute 'meow'

default dict infinite depth

from collections import defaultdict

f = lambda: defaultdict(f)
recursive_defaultdict = defaultdict(f)

Ideen für PyCologne/PyBonn

  • statische Blogs/Webseiten mit Pelican
  • Vim als Python Editor/Unix als IDE
  • BLITZ: interaktive Widgets für IPython Notebook
  • Fossil DVCS

automated code quality checks

  • https://www.quantifiedcode.com Little Book of Python Anti Patterns
  • https://landscape.io
  • https://scrutinizer-ci.com/ (refactoring etc.)
  • https://www.codacy.com/projects (set weekly goals)
  • https://basicallydan.github.io/forkability/?u=geier&r=khal
  • https://linthub.io/recent
  • https://github.com/justinabrahms/imhotep

is this pythonic or isn’t it?

  • if len(list_of_things) == 0 vs if not list_of_things
  • ‘{}’.format() vs % formatting, logging!

Method resolution is (relatively) expensive

%%timeit
a = list()
for _ in range(1000):
    a.append(1)

10000 loops, best of 3: 75.6 µs per loop

or

%%timeit
a = list()
b = a.append
for _ in range(1000):
    b(1)

10000 loops, best of 3: 46.4 µs per loop

Python oddities

What is going to happen here?

l = 1, 2, [1, 2, 3, 4]
l[2] += 5, 6

What’s a?

a,b = a[5] = {}, 42

What will this print in python 2 and 3?

from __future__ import print_function

i = 1
x = [lambda: i for i in range(10)]

print(x[i]())
print(x[5]())

i = 4
print(x[i]())
print(x[4]())

= Python 3 awesomeness = == super() ==

class MyClass(OtherClass): 
    def something(self):
        super().something()

instead of

class MyClass(OtherClass): 
    def something(self):
        super(MyClass, self).something()

== division ==

1/2 = 0.5

instead of

1/2 = 0

(yes, I know about future)

== timestamp == datetime.timestamp()

== advanced tuple unpacking ==

>>> a, *b, c = [1, 2, 3, 4, 5]
>>> b
[2, 3, 4]

== no comparison of unorderable types ==

>>> 'three' > 3
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unorderable types: str() > int()

== keyword-only arguments ==

>>> def foo(*, a, b):
...     return a + b
...
>>> foo(1, 2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: foo() takes 0 positional arguments but 2 were given
>>> foo(a=1, b=2)
3

Banker’s Rounding

‘‘‘Or Awefullness?’’’

round to nearest even number:

>>> round(1.5)
2
>>> round(2.5)
2

Disassemble python code

def foo():
    a = 1
    b = 1 + a
    return a

import dis
dis.dis(foo)

or


python -m dis test.py

python 2 & 3: unicode vs str vs bytes

The way strings work in python 2 might be easier for people who only ever use ASCII text, but for (rough estimate) 90% of the world’s population (including me and almost everybody I helped learn python) ASCII-only isn’t good enough to express their native language. Those people run into hard to understand (and debug) (UnicodeDecodeError: … can’t decode byte … and so on) problems really early in their python experience when they use python 2.

Sure, when using python 3, you need to take the time to explain the difference between bytes and strings (and preferably unicode and encodings as well), but in my experience this is needed in python 2 exactly as much (see above). The main advantage of python 3 regarding string handling is, that str/byte issues surface when running your program for the first time, not only when you put in some non-ASCII characters, sometimes much later.