Você está na página 1de 120

SuperAdvanced

Python
Warning:ThisTalkAttractsZombies
Presented by Raymond Chandler III / @raymondchandler
AShameless
Plug
ACT1
CritcalPoint#1
Everythingisanobject!
WhatisaSet?
CriticalPoint#2
EverythinginPythoncanbe
groupedintoaset!
WhatisSet
Theory?
Abranchofmathematicsthat
definesrulesandoperations
forworkingwithSets
BasicSet
Concepts
UnionAB
IfmemberofA,B,orBoth
list_a = ['a', 'b', 'c']
list_b = ['b', 'd', 'c']

print(set(a) | set(b))
>>> set(['a', 'c', 'b', 'd'])
IntersectAnB
OnlyifmemberofBoth
list_a = ['a', 'b', 'c']
list_b = ['b', 'd', 'c']

print(set(a) & set(b))


>>> set(['c', 'b'])
SetDiffA\B
Ifit'samemberofA,butnot
MemberofB
s.symmetric_difference(t) s^t

list_a = ['a', 'b', 'c']


list_b = ['b', 'd', 'c']

print(set(a) - set(b))
>>> set(['a'])

print(set(b) - set(a))
>>> set(['d'])
SymmetricDiff
ABorAB
IfmemberofAorBbutNOT
Both(XOR)
list_a = ['a', 'b', 'c']
list_b = ['b', 'd', 'c']

print(set(a) ^ set(b))
>>> set(['a', 'd'])
Cartesian
Product-AxB
PairsthefirstelementofA
withthefirstelementofB
from itertools import product
list_a = ['a', 'b', 'c']
list_b = ['b', 'd', 'c']

print(list(product(list_a, list_b)))
>>> [('a', 'b'), ('a', 'd'), ('a', 'c'), ('b', 'b'), ...]
Thinkofall
Python
collectionsas
Sets
Whatis
Category
Theory?
Thestudyof"morphisms".
Thetransitionsofsetsto
othersets.
Functors,
Functors,
Functors!
CriticalPoint#3
A"morphism"occurswhen
weapplyafunctortoaset
thattransformsitinto
somethingelse.
CriticalPoint#4
Foranysetwecanapply
somenumberoffunctorsto
arriveatANYotherset
ThePoint?
AnythinginPythoncanbe
transformedintoanything
elsebysimplyapplying
functorstosets
ACT2
ListComprehension
my_list = [1, 2, 3, 4, 5, 6]
print([x * 2 for x in my_list])
>>> [2, 4, 6, 8, 10, 12]
DictComprehension
my_dict = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5, 'f': 6}
result = {k: v * 2 for k, v in my_dict}
print(result)
>>> {'a': 2, 'b': 4, 'c': 6, 'd': 8, 'e': 10, 'f': 12}
DictComprehension(cont.)
print(result.iterkeys())
>>> ['a', 'b', 'c', 'd', 'e', 'f']

print(result.itervalues())
>>> [2, 4, 6, 8, 10, 12]

print(result.iteritems())
>>> [('a', 2), ('b', 4), ('c', 6), ('d', 8), ('e', 10), ('f': 12)]
LambdaExpression
my_list = [1, 2, 3, 4, 5, 6]
def my_func(item):
return item * 2

print([my_func(x) for x in my_list])


>>> [2, 4, 6, 8, 10, 12]

other_func = lambda x: x * 2
print([other_func(x) for x in my_list])
>>> [2, 4, 6, 8, 10, 12]
Enumerate
my_first_list = ['a', 'b', 'c', 'd', 'e']
my_second_list = [1, 2, 3, 4, 5]
print(zip(my_first_list, my_second_list))
>>> [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]

print(enumerate(my_first_list))
>>> [(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd'), (4, 'e')]

print(enumerate(my_first_list, 3))
>>> [(3, 'a'), (4, 'b'), (5, 'c'), (6, 'd'), (7, 'e')]
Zip
my_first_list = ['a', 'b', 'c', 'd', 'e']
my_second_list = [1, 2, 3, 4, 5]
print(zip(my_first_list, my_second_list))
>>> [('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]

my_second_list = ['z', 'y', 'x', 'w', 'v']


print(zip(my_first_list, my_second_list))
>>> [('a', 'z'), ('b', 'y'), ('c', 'x'), ('d', 'w'), ('e', 'v')]
ComplexExamples
my_first_list = "abcde"
my_second_list = "zyxwv"
result = zip(my_first_list, my_second_list)
print(result)
>>> [('a', 'z'), ('b', 'y'), ('c', 'x'), ('d', 'w'), ('e', 'v')]

result2 = [''.join(x) for x in result]


print(result2)
>>> ['az', 'by', 'cx', 'dw', 'ev']
ComplexExamples(cont)
result = zip("abcde", "zyxwv")
print(dict(result))
>>> {'a': 'z', 'c': 'x', 'b': 'y', 'd': 'w'}

print(dict([(k * 3, v) for k, v in result]))


>>> {'aaa': 'z', 'bbb': 'y', 'ccc': 'x', 'ddd': 'w'}
The"filter"builtin
my_list = [1, 2, 3, 4, 5, 6]
print([x for x in my_list if x % 2 == 0])
>>> [2, 4, 6]

print(filter(lambda x: x % 2 == 0, my_list))
>>> [2, 4, 6]
The"any"and"all"builtins
my_list = [True, False, False, False]
print(any(my_list))
>>> True

print(all(my_list))
>>> False

my_list = [True, True, True]


print(all(my_list))
>>> True
The"map"builtin
my_list = range(1, 7)
print(my_list)
>>> [1, 2, 3, 4, 5, 6]

print([x * 2 for x in my_list])


>>> [2, 4, 6, 8, 10, 12]

print(map(lambda x: x * 2, my_list))
>>> [2, 4, 6, 8, 10, 12]
The"reduce"builtin
val = 0
for x in range(1, 7):
val += my_list
print(val)
>>> 21

print(reduce(lambda x, y: x + y, range(1, 7)))


>>> 21

print(reduce(lambda x, y: x * y, range(1, 7)))


>>> 720
The"sum"builtin
print(reduce(lambda x, y: x + y, range(1, 7)))
>>> 21

print(sum(range(1,7)))
>>> 21
ACT3
Whatisa
closure?
Aclosureisafunctionthat
wrapsaroundanother
functionandsomenumberof
variablesand'closesover'or
'traps'whatitcontainsinit's
ownscope.
Startwiththeinnerpart
def multiply_numbers(x, y):
return x * y

print(multiply_numbers(3, 5))
>>> 15
Wraptheinnerpart
def mult_closure(x):
def wrapped(y):
#wrapped closes over the 'x' variable
return x * y
return wrapped
ClosureExample
#this returns wrapped with 3 enclosed as 'x'
mult_by_three = mult_closure(3)

print(mult_by_three(5))
>>> 15
print(mult_by_three(10))
>>> 30
Closures(cont)
#this returns wrapped with 10 enclosed as 'x'
mult_by_ten = mult_closure(10)

print(mult_by_ten(5))
>>> 50
print(mult_by_ten(15))
>>> 150
Whentouseaclosure?
Great to DRY up code. Add Syntactic Sugar.
You need to write a complicated generator.
Monkey Patch a function you can't change.
Dynamically build behavior by 'stacking' functions.
MonkeyPatchExample
def bad_function_from_library(some_attr): #You didn't write this.
some_attr / 0 #Oh noes!

print(bad_function_from_library(10))
>>> ZeroDivisionError: integer division or modulo by zero
MonkeyPatch(cont.)
def dont_panic_closure(bad_func):
def wrapped(some_attr):
try:
bad_func(some_attr) #wrapped closes over bad_func
except:
print("The bad function unleashed Zombies!")
return wrapped

catch_it = dont_panic_closure(bad_function_from_library)
print(catch_it(10))
>>> The bad function unleashed Zombies!
Whatisa
decorator?
DecoratorExample
def dont_panic(bad_func):
def wrapped(some_attr):
try:
bad_func(some_attr) #wrapped closes over bad_func
except:
print("The bad function unleashed Zombies!")
return wrapped
DecoratorExample(cont.)
@dont_panic
def bad_function_i_wrote(some_attr): #You totally wrote this.
some_attr / 0 #Oh noes!

print(bad_function_i_wrote(10))
>>> The bad function unleashed Zombies!
@issyntacticsugarfor
closingoverafunction
Letslogit!
def logger(func_to_log):
def wrapped(*args, **kwargs):
print("Arguments were: %s, %s" % (args, kwargs))
func_to_log(*args, **kwargs) #call the real function
return wrapped

@logger
def my_func(x, y):
return x * y

print(my_func(10, 15))
>>> Arguments were (10, 15), {}
>>> 150
ACT4
Whatisthedifference
betweenanIteratoranda
Generator?
Abasicgenerator
def step(start=0, step=1):
_start = start
while True:
yield _start
_start += step

stepper = step(10, 2)
Abasicgenerator(cont.)
print(stepper.next())
>>> 10
print(stepper.next())
>>> 12
print(stepper.next())
>>> 14
yieldisboththeexitand
entrypointforthegenerator
Whatwilllist(stepper)do?
Letsfixthat
def step(start=0, step=1, end=50):
_start = start
while _start < end:
yield _start
_start += step
Letsfixthat(cont.)
stepper = step(10, 10)
print(list(stepper))
>>> [10, 20, 30, 40]
stepper = step(30, 5, 60)
print(list(stepper))
>>> [30, 35, 40, 45, 50, 55]
AGeneratorExpression
stepper = (x * 5 for x in range(0, 10))
print(list(stepper))
>>> [0, 5, 10, 15, 20, 25, 30, 35, 40, 45]
stepper = (x ** 2 for x in range(0, 5))
print(list(stepper))
>>> [0, 1, 4, 9, 16]
Lookfamiliar?
Whyusegenerators?
Work with large data sets
Don't need to hold the entire list in memory.
Processing data in realtime.
ACT5
The'itertools'
Library
chain(*seq)
from itertools import chain
list_a = ['a', 'b', 'c']
list_b = range(1,4)
print(list(chain(list_a, list_b))
>>> ['a', 'b', 'c', 1, 2, 3]
combinations
from itertools import combinations

my_list = 'abc'
print(list(combinations(my_list, 2))
>>> [('a', 'b'), ('a', 'c'), ('b', 'c')]

my_list = range(1,6)
print(list(combinations(my_list, 4))
>>> [(1, 2, 3, 4), (1, 2, 3, 5), (1, 2, 4, 5), (1, 3, 4, 5), (2, 3, 4, 5)]
permutations
from itertools import permutations

my_list = 'abc'
print(list(permutations(my_list, 2))
>>> [('a', 'b'), ('a', 'c'), ('b', 'a'),
>>> ('b', 'c'), ('c', 'a'), ('c', 'b')]

my_list = range(1,6)
print(list(permutations(my_list, 2))
>>> [(1, 2), (1, 3), (1, 4), (1, 5), (2, 1),
>>> (2, 3), (2, 4), (2, 5), (3, 1), (3, 2),
>>> (3, 4), (3, 5), (4, 1), (4, 2), (4, 3),
>>> (4, 5), (5, 1), (5, 2), (5, 3), (5, 4)]
compress
from itertools import compress

my_list = 'abcdef'
my_slectors = [1,0,1,1,0,1]
print(list(compress(my_list, my_selectors))
>>> ['a', 'c', 'd', 'e', 'f']

print([v for v, s in zip(my_list, my_selectors) if s])


>>> ['a', 'c', 'd', 'e', 'f']
count
from itertools import count

counter = count(1, 5)
for l in 'abc':
print(' '.join(l, str(counter.next())))
>>> a 1
>>> b 6
>>> c 11
cycle
from itertools import cycle

i_want_to_ride_my_bi = cycle('abc123')
print([i_want_to_ride_my_bi.next() for i in range(0,10)])
>>> ['a', 'b', 'c', 1, 2, 3, 'a', 'b', 'c']
groupby
from itertools import groupby

my_list='aaaaabbbbcccdd' #sorted
print(list(groupby(my_list)))
>>> [('a', <itertools._grouper object at 0x10fd76410>),
>>> ('b', <itertools._grouper object at 0x10fd76450>),
>>> ...
groupby(cont.)
print({k:list(v) for k, v in groupby(my_list)})
>>> {'a': ['a', 'a', 'a', 'a', 'a'],
>>> 'c': ['c', 'c', 'c'],
>>> 'b': ['b', 'b', 'b', 'b'],
>>> 'd': ['d', 'd']}
groupby(cont.)
my_list = [
{'id': 1, 'name': 'raymond'},
{'id': 1, 'name': 'bob'},
{'id': 2, 'name': 'sue'}]

print({k:list(v) for k, v in groupby(my_list,


key=lambda x: x['id')})
>>> {1: [{'id': 1, 'name': 'raymond'},
>>> {'id': 1, 'name': 'bob'}],
>>> 2: [{'id': 2, 'name': 'sue'}]}
groupby(cont.)
my_list = [
{'id': 1, 'name': 'raymond'},
{'id': 1, 'email': 'raymond@spkrbar.com'},
{'id': 2, 'name': 'sue'},
{'id': 2, 'email': 'sue@sallysue.com'}]

[ dict(
reduce(lambda y, z: y + z,
map(lambda x: x.items(), v)
)
) for k, v in groupby(my_list, key=lambda x: x['id']) ]
groupby(cont.)
>>> [{ 'email': 'raymond@spkrbar.com',
>>> 'id': 1,
>>> 'name': 'raymond'},
>>> { 'email': 'peggy@sue.com',
>>> 'id': 2,
>>> 'name': 'sue'}]
product
from itertools import product
list_a = 'abc'
list_b = [1, 2]

print(list(product(list_a, list_b)))
>>> [('a', '1'), ('a', '2'), ('b', '1'), ('b', '2'), ('c', '1'), ('c', '2')]

print({x[0]:x[1] for x in product(list_a, list_b)})


>>> {'a': '2', 'c': '2', 'b': '2'}
ifilter/imap/izip
Worksexactlylikefilter/map/zipexpectforonething.Whatis
it?
ACT6
Whatismetaprogramming?
Whatisintrospection?
Considerthis
class Swallow:
def __init__(self, airspeed, color):
self.airspeed = airspeed
self.color = color

unladen_bird = Swallow(34.2, 'black')


getattr
#Notice the attribute is a string
print(getattr(unladen_bird, 'airspeed'))
>>> 34.2
print(getattr(unladen_bird, 'color'))
>>> 'black'
print(getattr(unladen_bird, 'wingspan'))
>>> None
hasattr
#Notice the attribute is a string
print(hasattr(unladen_bird, 'airspeed'))
>>> True
print(hasattr(unladen_bird, 'wingspan'))
>>> False
setattr
#Notice the attribute is a string
print(getattr(unladen_bird, 'airspeed'))
>>> 34.2
setattr(unladen_bird, 'airspeed', 42)
print(getattr(unladen_bird, 'airspeed'))
>>> 42
setattr(cont.)
print(getattr(unladen_bird, 'wingspan'))
>>> None
setattr(unladen_bird, 'wingspan', 14)
>>> False
print(getattr(unladen_bird, 'wingspan'))
>>> 14
Thealmighty
type()
Rememberthis?
print(type(unladen_bird))
>>> <type 'instance'>

print(type(Swallow))
>>> <type 'classobj'>
print(Swallow.__class__)
>>> <type 'classobj'>

print(Swallow)
>>> <class __main__.Swallow at 0x1062a60b8>
print(unladen_bird.__class__)
>>> <class __main__.Swallow at 0x1062a60b8>
Whataboutthis?
print(type(unladen_bird.__class__))
>>> <type 'classobj'>

print(type(unladen_bird.__class)).__class__
>>> <type 'type'>
Wait...wat?
Huh?
print(type((35).__class__).__class__)
>>> <type 'type'>

print(type(('abc').__class__).__class__)
>>> <type 'type'>
Oh,Iknow.Becauseofthe
typekeyword?
print((35).__class__.__class__)
>>> <type 'type'>

print(('abc').__class__.__class__)
>>> <type 'type'>
Wat?
CriticalPoint#1
EverythingisanObject
Corollary
type()isPython'sGod
Object!
type(class_name,
parents[tuple],
attributes[dict])
type()creates
everything
Letscreateaclass
Bird = type('UnladenSwallow', (), {'airspeed': 42, 'wingspan': 15})
my_bird = Bird()

print(type(Bird))
>>> <type 'type'>
print(type(my_bird))
>>> <class '__main__.UnladenSwallow'>

print(my_bird.airspeed)
>>> 42
print(hasattr(my_bird, 'wingspan'))
>>> True
Whatisa
MetaClass?
Here'sahint
type()isaMetaClass
More
specifically...
AMetaClassisany
callable(functionorclass)
thatimplementstype's
functionsignature
Hereareacouple
Metaclasses
def my_meta_class(class_name, class_parents, class_attrs):
... do stuff
return type(class_name, class_parents, class_attrs)

class MyMetaclass(type):
def __new__(klass, class_name, class_parents, class_attrs):
... do stuff
return type.__new__(klass, class_name,
class_parents, class_attrs)
Whatcandoyouinthe'...do
stuff'part?
Look at the attributes
Set new attributes
Create functions dynamically
Traverse the parent classes
Change values in the class
type()creates
theclassnot
theinstance.
Sowhatdoesthisdo?
class ZombieKiller:
__metaclass__ = MyMetaClass
HeyPython,insteadofusing
type,usethisthinginstead!
Somerules...
#1Don'tusethem...ever
(unlessyouhaveto).
#2Ifyouarebuildinga
complicatedandhighly
dynamicAPIthen
metaclassesmaybeforyou.
#3Makeyourmetaclassa
class,notafunctionand
derivefromtype.
Whew!...
Ohshit...
Questions?

Você também pode gostar