Highlights a bunch of different Python tricks and tips - from the stupid to the awesome (and a bit of both).
See how to register a 'str'.decode('hail_mary') codec, call_functions[1, 2, 3] instead of call_functions(1, 2, 3), creating a "Clojure-like" threading syntax by overloading the pipe operator, create useful equality mocks by overloading the equality operator, ditch JSON for pySON and put together a tiny lisp based on Norvig's awesome article.
2. # python has... oddities
import sys
print >>sys.stdout, 'hello world!'
# hello world!
from __builtin__ import int
# ... uh thanks?
from __builtin__ import True as False
# uh oh...
from __future__ import braces
# ... SyntaxError: not a chance
3. likes_art = True
# trivia: what am i?
where_to_go = likes_art and 'museum' or 'nascar'
# this is another way to do it...
where_to_go = ('nascar', 'museum')[bool(likes_art)]
# lazily now!
where_to_go = (lambda: 'nascar', lambda: 'museum')[bool(likes_art)]()
# greanevrf - gunax tbq sbe clguba >2.5!
# jure_g_tb = 'zhfrhz' vs yvxrf_neg ryfr 'anfpne'
4. likes_art = True
# trivia: what am i?
where_to_go = likes_art and 'museum' or 'nascar'
# this is another way to do it...
where_to_go = ('nascar', 'museum')[bool(likes_art)]
# lazily now!
where_to_go = (lambda: 'nascar', lambda: 'museum')[bool(likes_art)]()
# ternaries - thank god for python >2.5!
where_to_go = 'museum' if likes_art else 'nascar'
6. # registering custom str encoding
def register_codec(name, encode=None, decode=None):
import codecs
if not encode:
def encode(val):
raise Exception(name + ' does not support encoding')
if not decode:
def decode(val):
raise Exception(name + ' does not support decoding')
def codec(searched_name):
if searched_name != name:
return None
return codecs.CodecInfo(
name=name, encode=encode, decode=decode)
codecs.register(codec)
16. # complementary magic methods for operators
class Man(object):
def __add__(self, right_other):
if right_other == 'Dog':
return 'best buds'
return self
def __radd__(self, left_other):
if left_other == 'Dog':
return 'bestest buds'
return self
print Man() + 'Dog'
# best buds
print 'Dog' + Man()
# bestest buds
17. # magic methods to act like you aren't using python
class pipe(object):
def __init__(self, func):
self.func = func
def __ror__(self, other):
return self.func(other)
def __call__(self, *a, **kw):
return pipe(lambda x: self.func(x, *a, **kw))
18. # magic methods to act like you aren't using python continued
@pipe
def _map(iterable, func):
return [func(i) for i in iterable]
@pipe
def _filter(iterable, func):
return [i for i in iterable if func(i)]
print (range(10)
| _map(lambda i: i * 3)
| _filter(lambda i: i % 2 == 0)
| _map(str))
# ['0', '6', '12', '18', '24']
19. # magic methods for elegant DSLs
class RegexEquals(object):
def __init__(self, regex):
import re
self.regex = re.compile(regex)
def __eq__(self, other):
return bool(self.regex.match(other))
class TypeEquals(object):
def __init__(self, *tipes):
self.tipes = tipes
def __eq__(self, other):
return isinstance(other, self.tipes)
20. # magic methods for elegant DSLs continued
URL = RegexEquals(r'(https?|ftp)://[^s/$.?#].[^s]*')
NUM = RegexEquals(r'd+')
INT = TypeEquals(int, long)
print 'larry' == URL
# False
print 'http://zapier.com/' == URL
# True
print '123' == NUM
# True
print {'url': 'http://zapier.com/', 'visits': 4} == {'url': URL, 'visits': INT}
# True
21. # magic methods for abuse
class DidYouMean(object):
def __getattr__(self, name):
if name.startswith('__'):
raise AttributeError('No magic did you mean.')
from difflib import SequenceMatcher
scored_attrs = [
(SequenceMatcher(None, name, attr).ratio(), attr)
for attr in dir(self) if not attr.startswith('__')
]
sorted_attrs = sorted([
(score, attr) for score, attr in scored_attrs if score > 0.5
], reverse=True)
best_name = next(iter(sorted_attrs), (None, None))[1]
if not best_name:
raise AttributeError('No "matching" `%s` attribute' % name)
return getattr(self, best_name)