SlideShare a Scribd company logo
1 of 82
Download to read offline
Elegant
Solutions for
Everyday
Python
Problems
Nina Zakharenko
@nnja
h!p://bit.ly/elegant-
python
ā„¹ There are links in these slides.
slides: h!p://bit.ly/elegant-python
This talk is for you if:
You're an intermediate python programmer
You're coming to python from another language
You want to learn about language features like: magic
methods, iterators, decorators, and context managers
@nnja
What
is
elegant code?
@nnja
How do we make code elegant?
We pick the right tool for the job!
Resources for converting from Python 2 -> 3
Beauty is
in the eye of
the beholder
magic
methods
Magic methods start and end with a double underscore
(dunder)
By implementing a few straightforward magic methods,
you can make your objects behave like built-ins such as:
numbers
lists
dictionaries
and more...
@nnja
class Money:
currency_rates = {
'$': 1,
'ā‚¬': 0.88,
}
def __init__(self, symbol, amount):
self.symbol = symbol
self.amount = amount
def __str__(self):
return '%s%.2f' % (self.symbol, self.amount)
@nnja
class Money:
currency_rates = {
'$': 1,
'ā‚¬': 0.88,
}
def __init__(self, symbol, amount):
self.symbol = symbol
self.amount = amount
def __str__(self):
return '%s%.2f' % (self.symbol, self.amount)
@nnja
class Money:
# deļ¬ned currency_rates, __init__, and str above...
def convert(self, other):
"""Convert other amount to our currency"""
new_amount = (
other.amount / self.currency_rates[other.symbol]
* self.currency_rates[self.symbol])
return Money(self.symbol, new_amount)
@nnja
__str__ in action
>>> soda_cost = Money('$', 5.25)
>>> print(soda_cost)
$5.25
>>> pizza_cost = Money('ā‚¬', 7.99)
>>> print(pizza_cost)
ā‚¬7.99
@nnja
class Money:
def __add__(self, other):
""" Add 2 Money instances using '+' """
new_amount = self.amount + self.convert(other).amount
return Money(self.symbol, new_amount)
@nnja
>>> soda_cost = Money('$', 5.25)
>>> pizza_cost = Money('ā‚¬', 7.99)
>>> print(soda_cost + pizza_cost)
$14.33
More on Magic Methods: Dive into Python3 - Special Method
Names
>>> soda_cost = Money('$', 5.25)
>>> pizza_cost = Money('ā‚¬', 7.99)
>>> print(soda_cost + pizza_cost)
$14.33
>>> print(pizza_cost + soda_cost)
ā‚¬12.61
More on Magic Methods: Dive into Python3 - Special Method
Names
some magic methods map to symbols
>>> d = {'one': 1, 'two': 2}
>>> d['two']
2
>>> d.__getitem__('two')
2
@nnja
other magic methods map to built-in functions
class SquareShape:
def __len__(self):
""" Return the number of sides in our shape """
return 4
>>> my_square = SquareShape()
>>> len(my_square)
4
@nnja
custom
iterators
image source
Making classes iterable
In order to be iterable, a class needs to implement
__iter__()
__iter__() must return an iterator
In order to be an iterator a class needs to implement
__next__() which must raise StopIteration when
there are no more items to return
Great explanation of iterable vs. iterator vs. generator
Scenario..
We have a Server instance running services on
different ports.
Some services are active, some are inactive.
When we loop over our the Server instance, we only
want to loop over active services.
@nnja
class IterableServer:
services = [
{'active': False, 'protocol': 'ftp', 'port': 21},
{'active': True, 'protocol': 'ssh', 'port': 22},
{'active': True, 'protocol': 'http', 'port': 80},
]
@nnja
class IterableServer:
def __init__(self):
self.current_pos = 0
def __iter__(self):
# can return self, because __next__ implemented
return self
def __next__(self):
while self.current_pos < len(self.services):
service = self.services[self.current_pos]
self.current_pos += 1
if service['active']:
return service['protocol'], service['port']
raise StopIteration
@nnja
class IterableServer:
def __init__(self):
self.current_pos = 0
def __iter__(self):
# can return self, because __next__ implemented
return self
def __next__(self):
while self.current_pos < len(self.services):
service = self.services[self.current_pos]
self.current_pos += 1
if service['active']:
return service['protocol'], service['port']
raise StopIteration
@nnja
>>> for protocol, port in IterableServer():
print('service %s on port %d' % (protocol, port))
service ssh on port 22
service http on port 80
loops over all active services ... not bad
@nnja
tip: use a generator
when your iterator doesn't need to
maintain a lot of state
(which is most of the time)
@nnja
class Server:
services = [
{'active': False, 'protocol': 'ftp', 'port': 21},
{'active': True, 'protocol': 'ssh', 'port': 22},
{'active': True, 'protocol': 'http', 'port': 21},
]
def __iter__(self):
for service in self.services:
if service['active']:
yield service['protocol'], service['port']
@nnja
class Server:
services = [
{'active': False, 'protocol': 'ftp', 'port': 21},
{'active': True, 'protocol': 'ssh', 'port': 22},
{'active': True, 'protocol': 'http', 'port': 21},
]
def __iter__(self):
for service in self.services:
if service['active']:
yield service['protocol'], service['port']
@nnja
Why does this work?
use single parenthesis ( ) to create a generator
comprehension
^ technically, a generator expression but I like this term better, and so does Ned
Batchelder
>>> my_gen = (num for num in range(1))
>>> my_gen
<generator object <genexpr> at 0x107581bf8>
@nnja
An iterator must implement __next__()
>>> next(my_gen) # __next__() maps to built-in next()
0
and raise StopIteration when there are no more elements
>>> next(my_gen)
... StopIteration Traceback (most recent call last)
see itertools for working with iterators
āœØ
Method
āœØ
Magic
@nnja
alias methods
class Word:
def __init__(self, word):
self.word = word
def __repr__(self):
return self.word
def __add__(self, other_word):
return Word('%s %s' % (self.word, other_word))
# Add an alias from method __add__ to the method concat
concat = __add__
@nnja
We can add an alias from __add__ to concat because
methods are just objects
>>> # remember, concat = __add__
>>> ļ¬rst_name = Word('Max')
>>> last_name = Word('Smith')
>>> ļ¬rst_name + last_name
Max Smith
>>> ļ¬rst_name.concat(last_name)
Max Smith
>>> Word.__add__ == Word.concat
True
@nnja
Dog class
>>> class Dog:
sound = 'Bark'
def speak(self):
print(self.sound + '!', self.sound + '!')
>>> my_dog = Dog()
>>> my_dog.speak()
Bark! Bark!
read the docs
getattr(object, name, default)
>>> class Dog:
sound = 'Bark'
def speak(self):
print(self.sound + '!', self.sound + '!')
>>> my_dog = Dog()
>>> my_dog.speak()
Bark! Bark!
>>> getattr(my_dog, 'speak')
<bound method Dog.speak of
<__main__.Dog object at 0x10b145f28>>
>>> speak_method = getattr(my_dog, 'speak')
>>> speak_method()
Bark! Bark!
getattr(object, name, default)
>>> class Dog:
sound = 'Bark'
def speak(self):
print(self.sound + '!', self.sound + '!')
>>> my_dog = Dog()
>>> my_dog.speak()
Bark! Bark!
>>> getattr(my_dog, 'speak')
<bound method Dog.speak of
<__main__.Dog object at 0x10b145f28>>
>>> speak_method = getattr(my_dog, 'speak')
>>> speak_method()
Bark! Bark!
Example: command line tool with dynamic commands
class Operations:
def say_hi(self, name):
print('Hello,', name)
def say_bye(self, name):
print('Goodbye,', name)
def default(self, arg):
print('This operation is not supported.')
if __name__ == '__main__':
operations = Operations()
# let's assume error handling
command, argument = input('> ').split()
getattr(operations, command, operations.default)(argument)
read the docs
Output
$ python demo.py
> say_hi Nina
Hello, Nina
> blah blah
This operation is not supported.
āœØ
additional reading - inverse of getattr() is setattr()
functools.partial(func, *args, **kwargs)
Return a new partial object which behaves like func
called with args & kwargs
if more arguments are passed in, they are appended
to args
if more keyword arguments are passed in, they extend
and override kwargs
read the docs on partials
functool.partial(func, *args, **kwargs)
# We want to be able to call this function on any int
# without having to specify the base.
>>> int('10010', base=2)
18
>>> from functools import partial
>>> basetwo = partial(int, base=2)
>>> basetwo
<functools.partial object at 0x1085a09f0>
>>> basetwo('10010')
18
read the docs on partials
functool.partial(func, *args, **kwargs)
# We want to be able to call this function on any int
# without having to specify the base.
>>> int('10010', base=2)
18
>>> from functools import partial
>>> basetwo = partial(int, base=2)
>>> basetwo
<functools.partial object at 0x1085a09f0>
>>> basetwo('10010')
18
read the docs on partials
functool.partial(func, *args, **kwargs)
# We want to be able to call this function on any int
# without having to specify the base.
>>> int('10010', base=2)
18
>>> from functools import partial
>>> basetwo = partial(int, base=2)
>>> basetwo
<functools.partial object at 0x1085a09f0>
>>> basetwo('10010')
18
read the docs on partials
magic methods
& method magic
in action!
photo credit
library I
!
: github.com/mozilla/agithub
agithub is a (poorly named) REST API client with
transparent syntax which facilitates rapid prototyping
ā€” on any REST API!
Implemented in ~400 lines.
Add support for any REST API in ~30 lines of code.
agithub knows everything it needs to about protocol
(REST, HTTP, etc), but assumes nothing about your
upstream API.
@nnja
deļ¬ne endpoint url & other connection properties
class GitHub(API):
def __init__(self, token=None, *args, **kwargs):
props = ConnectionProperties(
api_url = kwargs.pop('api_url', 'api.github.com'))
self.setClient(Client(*args, **kwargs))
self.setConnectionProperties(props)
@nnja
then, start using the API!
>>> gh = GitHub('token')
>>> status, data = gh.user.repos.get()
>>> # ^ Maps to GET /user/repos
>>> data
... ['tweeter', 'snipey', '...']
github.com/mozilla/agithub
404 if we provide a path that doesn't exist:
>>> gh = GitHub('token')
>>> status, data = gh.this.path.doesnt.exist.get()
>>> status
... 404
github.com/jpaugh/agithub
magic!
but, how?...
@nnja
class API:
def __getattr__(self, key):
return IncompleteRequest(self.client).__getattr__(key)
__getitem__ = __getattr__
class IncompleteRequest:
def __getattr__(self, key):
if key in self.client.http_methods:
htmlMethod = getattr(self.client, key)
return partial(htmlMethod, url=self.url)
else:
self.url += '/' + str(key)
return self
__getitem__ = __getattr__
class Client:
http_methods = ('get') # ...
def get(self, url, headers={}, **params):
return self.request('GET', url, None, headers)
github.com/jpaugh/agithub source: base.py
class API:
def __getattr__(self, key):
return IncompleteRequest(self.client).__getattr__(key)
__getitem__ = __getattr__
class IncompleteRequest:
def __getattr__(self, key):
if key in self.client.http_methods:
htmlMethod = getattr(self.client, key)
return partial(htmlMethod, url=self.url)
else:
self.url += '/' + str(key)
return self
__getitem__ = __getattr__
class Client:
http_methods = ('get') # ...
def get(self, url, headers={}, **params):
return self.request('GET', url, None, headers)
github.com/jpaugh/agithub source: base.py
class API:
def __getattr__(self, key):
return IncompleteRequest(self.client).__getattr__(key)
__getitem__ = __getattr__
class IncompleteRequest:
def __getattr__(self, key):
if key in self.client.http_methods:
htmlMethod = getattr(self.client, key)
return partial(htmlMethod, url=self.url)
else:
self.url += '/' + str(key)
return self
__getitem__ = __getattr__
class Client:
http_methods = ('get') # ...
def get(self, url, headers={}, **params):
return self.request('GET', url, None, headers)
github.com/jpaugh/agithub source: base.py
Context
Managers
@nnja
When should I use one?
Need to perform an action before and/or after an
operation.
Common scenarios:
Closing a resource after you're done with it (ļ¬le,
network connection)
Perform cleanup before/after a function call
@nnja
Example Problem: Feature Flags
Turn features of your application on and off easily.
Uses of feature ļ¬‚ags:
A/B Testing
Rolling Releases
Show Beta version to users opted-in to Beta Testing
Program
More on Feature Flags
class FeatureFlags:
SHOW_BETA = 'Show Beta version of Home Page'
ļ¬‚ags = {
SHOW_BETA: True
}
@classmethod
def is_on(cls, name):
return cls.ļ¬‚ags[name]
@classmethod
def toggle(cls, name, value):
cls.ļ¬‚ags[name] = value
feature_ļ¬‚ags = FeatureFlags()
@nnja
How do we temporarily turn features on and off when
testing ļ¬‚ags?
Want:
with feature_ļ¬‚ag(FeatureFlags.SHOW_BETA):
assert '/beta' == get_homepage_url()
@nnja
Using Magic Methods __enter__ and __exit__
class feature_ļ¬‚ag:
""" Implementing a Context Manager using Magic Methods """
def __init__(self, name, on=True):
self.name = name
self.on = on
self.old_value = feature_ļ¬‚ags.is_on(name)
def __enter__(self):
feature_ļ¬‚ags.toggle(self.name, self.on)
def __exit__(self, *args):
feature_ļ¬‚ags.toggle(self.name, self.old_value)
See: contextlib.contextmanager
The be!er way: using the contextmanager decorator
from contextlib import contextmanager
@contextmanager
def feature_ļ¬‚ag(name, on=True):
old_value = feature_ļ¬‚ags.is_on(name)
feature_ļ¬‚ags.toggle(name, on)
yield
feature_ļ¬‚ags.toggle(name, old_value)
See: contextlib.contextmanager
The be!er way: using the contextmanager decorator
from contextlib import contextmanager
@contextmanager
def feature_ļ¬‚ag(name, on=True):
""" The easier way to create Context Managers """
old_value = feature_ļ¬‚ags.is_on(name)
# behavior of __enter__()
feature_ļ¬‚ags.toggle(name, on)
yield
# behavior of __exit__()
feature_ļ¬‚ags.toggle(name, old_value)
See: contextlib.contextmanager
Note: yield?
from contextlib import contextmanager
@contextmanager
def feature_ļ¬‚ag(name, on=True):
""" The easier way to create Context Managers """
old_value = feature_ļ¬‚ags.is_on(name)
feature_ļ¬‚ags.toggle(name, on) # behavior of __enter__()
yield
feature_ļ¬‚ags.toggle(name, old_value) # behavior of __exit__()
See: contextlib.contextmanager
either implementation
def get_homepage_url():
""" Returns the path of the page to display """
if feature_ļ¬‚ags.is_on(FeatureFlags.SHOW_BETA):
return '/beta'
else:
return '/homepage'
def test_homepage_url_with_context_manager():
with feature_ļ¬‚ag(FeatureFlags.SHOW_BETA):
# saw the beta homepage...
assert get_homepage_url() == '/beta'
with feature_ļ¬‚ag(FeatureFlags.SHOW_BETA, on=False):
# saw the standard homepage...
assert get_homepage_url() == '/homepage'
either implementation
def get_homepage_url():
""" Returns the path of the page to display """
if feature_ļ¬‚ags.is_on(FeatureFlags.SHOW_BETA):
return '/beta'
else:
return '/homepage'
def test_homepage_url_with_context_manager():
with feature_ļ¬‚ag(FeatureFlags.SHOW_BETA):
assert get_homepage_url() == '/beta'
print('seeing the beta homepage...')
with feature_ļ¬‚ag(FeatureFlags.SHOW_BETA, on=False):
assert get_homepage_url() == '/homepage'
print('seeing the standard homepage...')
Decorators
The simple explanation:
Syntactic sugar that allows modiļ¬cation of an underlying
function.
@nnja
Decorators:
Wrap a function in another function.
Do something:
before the call
after the call
with provided arguments
modify the return value or arguments
@nnja
class User:
is_authenticated = False
def __init__(self, name):
self.name = name
Throw an exception if trying to access data only for
logged in users:
def display_proļ¬le_page(user):
""" Display proļ¬le page for logged in User """
if not user.is_authenticated:
raise Exception('User must login.')
print('Proļ¬le: %s' % user.name)
def enforce_authentication(func):
def wrapper(user):
if not user.is_authenticated:
raise Exception('User must login.')
return func(user)
return wrapper
the important logic:
def enforce_authentication(func):
def wrapper(user):
if not user.is_authenticated:
raise Exception('User must login.')
return func(user)
return wrapper
@nnja
Using enforce_authentication without a decorator:
enforce_authentication(display_proļ¬le_page)(some_user)
Or, as a decorator:
@enforce_authentication
def display_proļ¬le_page(user):
print('Proļ¬le: %s' % user.name)
Now this raises an Exception if unauthenticated:
user = User('nina')
display_proļ¬le_page(nina)
Problem: lost context using a decorator
>>> display_proļ¬le_page.__name__
'wrapper'
>>>> display_proļ¬le_page.__doc__
# ... empty
Solution: Use contextlib.wraps
from contextlib import wraps
def enforce_authentication(func):
@wraps(func)
def wrapper(user):
# ... rest of the code
Decorators: Common uses
logging
timing
validation
rate limiting
mocking/patching
@nnja
ContextDecorators
ContextManagers
+ Decorators combined.
@nnja
By using ContextDecorator you can easily write
classes that can be used both as decorators with @
and context managers with the with statement.
ContextDecorator is used by contextmanager(),
so you get this functionality automatically .
Or, you can write a class that extends from
ContextDecorator or uses ContextDecorator as a
mixin, and implements __enter__, __exit__ and
__call__
@nnja
Remember @contextmanager from earlier?
from contextlib import contextmanager
@contextmanager
def feature_ļ¬‚ag(name, on=True):
old_value = feature_ļ¬‚ags.is_on(name)
feature_ļ¬‚ags.toggle(name, on)
yield
feature_ļ¬‚ags.toggle(name, old_value)
@nnja
use it as a context manager
with feature_ļ¬‚ag(FeatureFlags.SHOW_BETA):
assert get_homepage_url() == '/beta'
or use as a decorator
@feature_ļ¬‚ag(FeatureFlags.SHOW_BETA, on=False)
def get_proļ¬le_page():
beta_ļ¬‚ag_on = feature_ļ¬‚ags.is_on(
FeatureFlags.SHOW_BETA)
if beta_ļ¬‚ag_on:
return 'beta.html'
else:
return 'proļ¬le.html'
library I
!
: freezegun
lets your python tests ā‡ travel through time! ā‡
from freezegun import freeze_time
# use it as a Context Manager
def test():
with freeze_time("2012-01-14"):
assert datetime.datetime.now() == datetime.datetime(
2012, 1, 14)
assert datetime.datetime.now() != datetime.datetime(2012, 1, 14)
# or a decorator
@freeze_time("2012-01-14")
def test():
assert datetime.datetime.now() == datetime.datetime(2012, 1, 14)
read the source sometime, it's mind-bending!
NamedTuple
Useful when you need lightweight representations of
data.
Create tuple subclasses with named ļ¬elds.
@nnja
Example
from collections import namedtuple
CacheInfo = namedtuple(
"CacheInfo", ["hits", "misses", "max_size", "curr_size"])
@nnja
Giving NamedTuples default values
RoutingRule = namedtuple(
'RoutingRule',
['preļ¬x', 'queue_name', 'wait_time']
)
(1) By specifying defaults
RoutingRule.__new__.__defaults__ = (None, None, 20)
(2) or with _replace to customize a prototype instance
default_rule = RoutingRule(None, None, 20)
user_rule = default_rule._replace(
preļ¬x='user', queue_name='user-queue')
NamedTuples can be subclassed and extended
class Person(namedtuple('Person', ['ļ¬rst_name', 'last_name'])):
""" Stores ļ¬rst and last name of a Person"""
def __str__(self):
return '%s %s' % (self.ļ¬rst_name, self.last_name)
>>> me = Person('nina', 'zakharenko')
>>> str(me)
'nina zakharenko'
>>> me
Person(ļ¬rst_name='nina', last_name='zakharenko')
New Tools
Magic Methods
make your objects behave like builtins (numbers,
list, dict, etc)
Method ā‡Magicā‡
alias methods
getattr
@nnja
ContextManagers
Manage resources
Decorators
do something before/after call, modify return value
or validate arguments
ContextDecorators
ContextManagers + Decorators in one
@nnja
Iterators & Generators
Loop over your objects
yield
NamedTuple
Lightweight classes
@nnja
"Perfection is achieved, not when
there is nothing more to add, but
when there is nothing left to take
away."
ā€” Antoine de Saint-Exupery
@nnja
Be an
elegant
Pythonista!
@nnja
Thanks!
slides: bit.ly/elegant-python
python@ microso! aka.ms/python
@nnja
@nnja

More Related Content

What's hot

Akka.NET ģœ¼ė”œ ė§Œė“œėŠ” ģ˜Øė¼ģø ź²Œģž„ ģ„œė²„ (NDC2016)
Akka.NET ģœ¼ė”œ ė§Œė“œėŠ” ģ˜Øė¼ģø ź²Œģž„ ģ„œė²„ (NDC2016)Akka.NET ģœ¼ė”œ ė§Œė“œėŠ” ģ˜Øė¼ģø ź²Œģž„ ģ„œė²„ (NDC2016)
Akka.NET ģœ¼ė”œ ė§Œė“œėŠ” ģ˜Øė¼ģø ź²Œģž„ ģ„œė²„ (NDC2016)Esun Kim
Ā 
ģ‹¤ģ‹œź°„ ź²Œģž„ ģ„œė²„ ģµœģ ķ™” ģ „ėžµ
ģ‹¤ģ‹œź°„ ź²Œģž„ ģ„œė²„ ģµœģ ķ™” ģ „ėžµģ‹¤ģ‹œź°„ ź²Œģž„ ģ„œė²„ ģµœģ ķ™” ģ „ėžµ
ģ‹¤ģ‹œź°„ ź²Œģž„ ģ„œė²„ ģµœģ ķ™” ģ „ėžµYEONG-CHEON YOU
Ā 
Git training
Git trainingGit training
Git trainingeric7master
Ā 
IntelON 2021 Processor Benchmarking
IntelON 2021 Processor BenchmarkingIntelON 2021 Processor Benchmarking
IntelON 2021 Processor BenchmarkingBrendan Gregg
Ā 
ķŒŒģ“ģ¬ TDD 101
ķŒŒģ“ģ¬ TDD 101ķŒŒģ“ģ¬ TDD 101
ķŒŒģ“ģ¬ TDD 101ģ •ģ£¼ ź¹€
Ā 
GitHub ģ‹¤ģŠµ źµģœ”
GitHub ģ‹¤ģŠµ źµģœ”GitHub ģ‹¤ģŠµ źµģœ”
GitHub ģ‹¤ģŠµ źµģœ”ģŠ¹ģ—½ ģ‹ 
Ā 
ź²Œģž„ģ„œė²„ķ”„ė”œź·øėž˜ė° #7 - ķŒØķ‚·ķ•øė“¤ė§ ė° ģ•”ķ˜øķ™”
ź²Œģž„ģ„œė²„ķ”„ė”œź·øėž˜ė° #7 - ķŒØķ‚·ķ•øė“¤ė§ ė° ģ•”ķ˜øķ™”ź²Œģž„ģ„œė²„ķ”„ė”œź·øėž˜ė° #7 - ķŒØķ‚·ķ•øė“¤ė§ ė° ģ•”ķ˜øķ™”
ź²Œģž„ģ„œė²„ķ”„ė”œź·øėž˜ė° #7 - ķŒØķ‚·ķ•øė“¤ė§ ė° ģ•”ķ˜øķ™”Seungmo Koo
Ā 
Next-generation MMORPG service architecture
Next-generation MMORPG service architectureNext-generation MMORPG service architecture
Next-generation MMORPG service architectureJongwon Kim
Ā 
Functional Programming 101 with Scala and ZIO @FunctionalWorld
Functional Programming 101 with Scala and ZIO @FunctionalWorldFunctional Programming 101 with Scala and ZIO @FunctionalWorld
Functional Programming 101 with Scala and ZIO @FunctionalWorldJorge VƔsquez
Ā 
emruby: ćƒ–ćƒ©ć‚¦ć‚¶ć§å‹•ćRuby
emruby: ćƒ–ćƒ©ć‚¦ć‚¶ć§å‹•ćRubyemruby: ćƒ–ćƒ©ć‚¦ć‚¶ć§å‹•ćRuby
emruby: ćƒ–ćƒ©ć‚¦ć‚¶ć§å‹•ćRubymametter
Ā 
Stop the Guessing: Performance Methodologies for Production Systems
Stop the Guessing: Performance Methodologies for Production SystemsStop the Guessing: Performance Methodologies for Production Systems
Stop the Guessing: Performance Methodologies for Production SystemsBrendan Gregg
Ā 
ģ“ė¬“ė¦¼, Enumģ˜ Boxingģ„ ģ–“ģ°Œķ• ź¼¬? ķŽøė¦¬ķ•˜ź³  ģ„±ėŠ„ģ¢‹ź²Œ Enum ģ‚¬ģš©ķ•˜źø°, NDC2019
ģ“ė¬“ė¦¼, Enumģ˜ Boxingģ„ ģ–“ģ°Œķ• ź¼¬? ķŽøė¦¬ķ•˜ź³  ģ„±ėŠ„ģ¢‹ź²Œ Enum ģ‚¬ģš©ķ•˜źø°, NDC2019ģ“ė¬“ė¦¼, Enumģ˜ Boxingģ„ ģ–“ģ°Œķ• ź¼¬? ķŽøė¦¬ķ•˜ź³  ģ„±ėŠ„ģ¢‹ź²Œ Enum ģ‚¬ģš©ķ•˜źø°, NDC2019
ģ“ė¬“ė¦¼, Enumģ˜ Boxingģ„ ģ–“ģ°Œķ• ź¼¬? ķŽøė¦¬ķ•˜ź³  ģ„±ėŠ„ģ¢‹ź²Œ Enum ģ‚¬ģš©ķ•˜źø°, NDC2019devCAT Studio, NEXON
Ā 
[ģ•¼ģƒģ˜ ė•…: ė“€ėž‘ź³ ] ģ„œė²„ ģ•„ķ‚¤ķ…ģ²˜ - SPOF ģ—†ėŠ” ė¶„ģ‚° MMORPG ģ„œė²„
[ģ•¼ģƒģ˜ ė•…: ė“€ėž‘ź³ ] ģ„œė²„ ģ•„ķ‚¤ķ…ģ²˜ - SPOF ģ—†ėŠ” ė¶„ģ‚° MMORPG ģ„œė²„[ģ•¼ģƒģ˜ ė•…: ė“€ėž‘ź³ ] ģ„œė²„ ģ•„ķ‚¤ķ…ģ²˜ - SPOF ģ—†ėŠ” ė¶„ģ‚° MMORPG ģ„œė²„
[ģ•¼ģƒģ˜ ė•…: ė“€ėž‘ź³ ] ģ„œė²„ ģ•„ķ‚¤ķ…ģ²˜ - SPOF ģ—†ėŠ” ė¶„ģ‚° MMORPG ģ„œė²„Heungsub Lee
Ā 
ė¬“ģ •ģ§€&ė¬“ģ ź²€ ģ„œė²„ ź°œė°œź³¼ ģš“ģ˜ ģ‚¬ė”€
ė¬“ģ •ģ§€&ė¬“ģ ź²€ ģ„œė²„ ź°œė°œź³¼ ģš“ģ˜ ģ‚¬ė”€ė¬“ģ •ģ§€&ė¬“ģ ź²€ ģ„œė²„ ź°œė°œź³¼ ģš“ģ˜ ģ‚¬ė”€
ė¬“ģ •ģ§€&ė¬“ģ ź²€ ģ„œė²„ ź°œė°œź³¼ ģš“ģ˜ ģ‚¬ė”€Taehyun Kim
Ā 
Gitlab with github desktop
Gitlab with github desktopGitlab with github desktop
Gitlab with github desktopSagar Dash
Ā 
Kubernetes Failure Stories - KubeCon Europe Barcelona
Kubernetes Failure Stories - KubeCon Europe BarcelonaKubernetes Failure Stories - KubeCon Europe Barcelona
Kubernetes Failure Stories - KubeCon Europe BarcelonaHenning Jacobs
Ā 
Java Performance Analysis on Linux with Flame Graphs
Java Performance Analysis on Linux with Flame GraphsJava Performance Analysis on Linux with Flame Graphs
Java Performance Analysis on Linux with Flame GraphsBrendan Gregg
Ā 
ź²Œģž„ ź°œė°œ ķŒŒģ“ķ”„ė¼ģøź³¼ ģ‹œģŠ¤ķ…œ źø°ķš(ź³µź°œģš©)
ź²Œģž„ ź°œė°œ ķŒŒģ“ķ”„ė¼ģøź³¼ ģ‹œģŠ¤ķ…œ źø°ķš(ź³µź°œģš©)ź²Œģž„ ź°œė°œ ķŒŒģ“ķ”„ė¼ģøź³¼ ģ‹œģŠ¤ķ…œ źø°ķš(ź³µź°œģš©)
ź²Œģž„ ź°œė°œ ķŒŒģ“ķ”„ė¼ģøź³¼ ģ‹œģŠ¤ķ…œ źø°ķš(ź³µź°œģš©)ChangHyun Won
Ā 
AI ė“œė”  ķ”„ė”œź·øėž˜ė°
AI ė“œė”  ķ”„ė”œź·øėž˜ė°AI ė“œė”  ķ”„ė”œź·øėž˜ė°
AI ė“œė”  ķ”„ė”œź·øėž˜ė°JongHyunKim78
Ā 
Shell Scripting Tutorial | Edureka
Shell Scripting Tutorial | EdurekaShell Scripting Tutorial | Edureka
Shell Scripting Tutorial | EdurekaEdureka!
Ā 

What's hot (20)

Akka.NET ģœ¼ė”œ ė§Œė“œėŠ” ģ˜Øė¼ģø ź²Œģž„ ģ„œė²„ (NDC2016)
Akka.NET ģœ¼ė”œ ė§Œė“œėŠ” ģ˜Øė¼ģø ź²Œģž„ ģ„œė²„ (NDC2016)Akka.NET ģœ¼ė”œ ė§Œė“œėŠ” ģ˜Øė¼ģø ź²Œģž„ ģ„œė²„ (NDC2016)
Akka.NET ģœ¼ė”œ ė§Œė“œėŠ” ģ˜Øė¼ģø ź²Œģž„ ģ„œė²„ (NDC2016)
Ā 
ģ‹¤ģ‹œź°„ ź²Œģž„ ģ„œė²„ ģµœģ ķ™” ģ „ėžµ
ģ‹¤ģ‹œź°„ ź²Œģž„ ģ„œė²„ ģµœģ ķ™” ģ „ėžµģ‹¤ģ‹œź°„ ź²Œģž„ ģ„œė²„ ģµœģ ķ™” ģ „ėžµ
ģ‹¤ģ‹œź°„ ź²Œģž„ ģ„œė²„ ģµœģ ķ™” ģ „ėžµ
Ā 
Git training
Git trainingGit training
Git training
Ā 
IntelON 2021 Processor Benchmarking
IntelON 2021 Processor BenchmarkingIntelON 2021 Processor Benchmarking
IntelON 2021 Processor Benchmarking
Ā 
ķŒŒģ“ģ¬ TDD 101
ķŒŒģ“ģ¬ TDD 101ķŒŒģ“ģ¬ TDD 101
ķŒŒģ“ģ¬ TDD 101
Ā 
GitHub ģ‹¤ģŠµ źµģœ”
GitHub ģ‹¤ģŠµ źµģœ”GitHub ģ‹¤ģŠµ źµģœ”
GitHub ģ‹¤ģŠµ źµģœ”
Ā 
ź²Œģž„ģ„œė²„ķ”„ė”œź·øėž˜ė° #7 - ķŒØķ‚·ķ•øė“¤ė§ ė° ģ•”ķ˜øķ™”
ź²Œģž„ģ„œė²„ķ”„ė”œź·øėž˜ė° #7 - ķŒØķ‚·ķ•øė“¤ė§ ė° ģ•”ķ˜øķ™”ź²Œģž„ģ„œė²„ķ”„ė”œź·øėž˜ė° #7 - ķŒØķ‚·ķ•øė“¤ė§ ė° ģ•”ķ˜øķ™”
ź²Œģž„ģ„œė²„ķ”„ė”œź·øėž˜ė° #7 - ķŒØķ‚·ķ•øė“¤ė§ ė° ģ•”ķ˜øķ™”
Ā 
Next-generation MMORPG service architecture
Next-generation MMORPG service architectureNext-generation MMORPG service architecture
Next-generation MMORPG service architecture
Ā 
Functional Programming 101 with Scala and ZIO @FunctionalWorld
Functional Programming 101 with Scala and ZIO @FunctionalWorldFunctional Programming 101 with Scala and ZIO @FunctionalWorld
Functional Programming 101 with Scala and ZIO @FunctionalWorld
Ā 
emruby: ćƒ–ćƒ©ć‚¦ć‚¶ć§å‹•ćRuby
emruby: ćƒ–ćƒ©ć‚¦ć‚¶ć§å‹•ćRubyemruby: ćƒ–ćƒ©ć‚¦ć‚¶ć§å‹•ćRuby
emruby: ćƒ–ćƒ©ć‚¦ć‚¶ć§å‹•ćRuby
Ā 
Stop the Guessing: Performance Methodologies for Production Systems
Stop the Guessing: Performance Methodologies for Production SystemsStop the Guessing: Performance Methodologies for Production Systems
Stop the Guessing: Performance Methodologies for Production Systems
Ā 
ģ“ė¬“ė¦¼, Enumģ˜ Boxingģ„ ģ–“ģ°Œķ• ź¼¬? ķŽøė¦¬ķ•˜ź³  ģ„±ėŠ„ģ¢‹ź²Œ Enum ģ‚¬ģš©ķ•˜źø°, NDC2019
ģ“ė¬“ė¦¼, Enumģ˜ Boxingģ„ ģ–“ģ°Œķ• ź¼¬? ķŽøė¦¬ķ•˜ź³  ģ„±ėŠ„ģ¢‹ź²Œ Enum ģ‚¬ģš©ķ•˜źø°, NDC2019ģ“ė¬“ė¦¼, Enumģ˜ Boxingģ„ ģ–“ģ°Œķ• ź¼¬? ķŽøė¦¬ķ•˜ź³  ģ„±ėŠ„ģ¢‹ź²Œ Enum ģ‚¬ģš©ķ•˜źø°, NDC2019
ģ“ė¬“ė¦¼, Enumģ˜ Boxingģ„ ģ–“ģ°Œķ• ź¼¬? ķŽøė¦¬ķ•˜ź³  ģ„±ėŠ„ģ¢‹ź²Œ Enum ģ‚¬ģš©ķ•˜źø°, NDC2019
Ā 
[ģ•¼ģƒģ˜ ė•…: ė“€ėž‘ź³ ] ģ„œė²„ ģ•„ķ‚¤ķ…ģ²˜ - SPOF ģ—†ėŠ” ė¶„ģ‚° MMORPG ģ„œė²„
[ģ•¼ģƒģ˜ ė•…: ė“€ėž‘ź³ ] ģ„œė²„ ģ•„ķ‚¤ķ…ģ²˜ - SPOF ģ—†ėŠ” ė¶„ģ‚° MMORPG ģ„œė²„[ģ•¼ģƒģ˜ ė•…: ė“€ėž‘ź³ ] ģ„œė²„ ģ•„ķ‚¤ķ…ģ²˜ - SPOF ģ—†ėŠ” ė¶„ģ‚° MMORPG ģ„œė²„
[ģ•¼ģƒģ˜ ė•…: ė“€ėž‘ź³ ] ģ„œė²„ ģ•„ķ‚¤ķ…ģ²˜ - SPOF ģ—†ėŠ” ė¶„ģ‚° MMORPG ģ„œė²„
Ā 
ė¬“ģ •ģ§€&ė¬“ģ ź²€ ģ„œė²„ ź°œė°œź³¼ ģš“ģ˜ ģ‚¬ė”€
ė¬“ģ •ģ§€&ė¬“ģ ź²€ ģ„œė²„ ź°œė°œź³¼ ģš“ģ˜ ģ‚¬ė”€ė¬“ģ •ģ§€&ė¬“ģ ź²€ ģ„œė²„ ź°œė°œź³¼ ģš“ģ˜ ģ‚¬ė”€
ė¬“ģ •ģ§€&ė¬“ģ ź²€ ģ„œė²„ ź°œė°œź³¼ ģš“ģ˜ ģ‚¬ė”€
Ā 
Gitlab with github desktop
Gitlab with github desktopGitlab with github desktop
Gitlab with github desktop
Ā 
Kubernetes Failure Stories - KubeCon Europe Barcelona
Kubernetes Failure Stories - KubeCon Europe BarcelonaKubernetes Failure Stories - KubeCon Europe Barcelona
Kubernetes Failure Stories - KubeCon Europe Barcelona
Ā 
Java Performance Analysis on Linux with Flame Graphs
Java Performance Analysis on Linux with Flame GraphsJava Performance Analysis on Linux with Flame Graphs
Java Performance Analysis on Linux with Flame Graphs
Ā 
ź²Œģž„ ź°œė°œ ķŒŒģ“ķ”„ė¼ģøź³¼ ģ‹œģŠ¤ķ…œ źø°ķš(ź³µź°œģš©)
ź²Œģž„ ź°œė°œ ķŒŒģ“ķ”„ė¼ģøź³¼ ģ‹œģŠ¤ķ…œ źø°ķš(ź³µź°œģš©)ź²Œģž„ ź°œė°œ ķŒŒģ“ķ”„ė¼ģøź³¼ ģ‹œģŠ¤ķ…œ źø°ķš(ź³µź°œģš©)
ź²Œģž„ ź°œė°œ ķŒŒģ“ķ”„ė¼ģøź³¼ ģ‹œģŠ¤ķ…œ źø°ķš(ź³µź°œģš©)
Ā 
AI ė“œė”  ķ”„ė”œź·øėž˜ė°
AI ė“œė”  ķ”„ė”œź·øėž˜ė°AI ė“œė”  ķ”„ė”œź·øėž˜ė°
AI ė“œė”  ķ”„ė”œź·øėž˜ė°
Ā 
Shell Scripting Tutorial | Edureka
Shell Scripting Tutorial | EdurekaShell Scripting Tutorial | Edureka
Shell Scripting Tutorial | Edureka
Ā 

Similar to Elegant Solutions for Everyday Python Problems Pycon 2018 - Nina Zakharenko

Elegant Solutions For Everyday Python Problems - PyCon Canada 2017
Elegant Solutions For Everyday Python Problems - PyCon Canada 2017Elegant Solutions For Everyday Python Problems - PyCon Canada 2017
Elegant Solutions For Everyday Python Problems - PyCon Canada 2017Nina Zakharenko
Ā 
Elegant Solutions For Everyday Python Problems - Nina Zakharenko
Elegant Solutions For Everyday Python Problems - Nina ZakharenkoElegant Solutions For Everyday Python Problems - Nina Zakharenko
Elegant Solutions For Everyday Python Problems - Nina ZakharenkoNina Zakharenko
Ā 
Python na Infraestrutura ā€ØMySQL do Facebookā€Ø
Python na Infraestrutura ā€ØMySQL do Facebookā€ØPython na Infraestrutura ā€ØMySQL do Facebookā€Ø
Python na Infraestrutura ā€ØMySQL do Facebookā€ØArtur Rodrigues
Ā 
Iterarators and generators in python
Iterarators and generators in pythonIterarators and generators in python
Iterarators and generators in pythonSarfaraz Ghanta
Ā 
python ppt.pptx
python ppt.pptxpython ppt.pptx
python ppt.pptxMONAR11
Ā 
Functions2.pptx
Functions2.pptxFunctions2.pptx
Functions2.pptxAkhilTyagi42
Ā 
C++ code, please help! RESPOND W COMPLETED CODE PLEASE, am using V.pdf
C++ code, please help! RESPOND W COMPLETED CODE PLEASE,  am using V.pdfC++ code, please help! RESPOND W COMPLETED CODE PLEASE,  am using V.pdf
C++ code, please help! RESPOND W COMPLETED CODE PLEASE, am using V.pdfrahulfancycorner21
Ā 
Python lecture 03
Python lecture 03Python lecture 03
Python lecture 03Tanwir Zaman
Ā 
Cc code cards
Cc code cardsCc code cards
Cc code cardsysolanki78
Ā 
Python_Functions_Unit1.pptx
Python_Functions_Unit1.pptxPython_Functions_Unit1.pptx
Python_Functions_Unit1.pptxKoteswari Kasireddy
Ā 
Introduction to python programming 2
Introduction to python programming   2Introduction to python programming   2
Introduction to python programming 2Giovanni Della Lunga
Ā 
Pythonlearn-04-Functions (1).pptx
Pythonlearn-04-Functions (1).pptxPythonlearn-04-Functions (1).pptx
Pythonlearn-04-Functions (1).pptxleavatin
Ā 
Functions_19_20.pdf
Functions_19_20.pdfFunctions_19_20.pdf
Functions_19_20.pdfpaijitk
Ā 
C++ Course - Lesson 2
C++ Course - Lesson 2C++ Course - Lesson 2
C++ Course - Lesson 2Mohamed Ahmed
Ā 
Advanced Web Technology ass.pdf
Advanced Web Technology ass.pdfAdvanced Web Technology ass.pdf
Advanced Web Technology ass.pdfsimenehanmut
Ā 
Functions2.pdf
Functions2.pdfFunctions2.pdf
Functions2.pdfprasnt1
Ā 
Generators & Decorators.pptx
Generators & Decorators.pptxGenerators & Decorators.pptx
Generators & Decorators.pptxIrfanShaik98
Ā 
Using-Python-Libraries.9485146.powerpoint.pptx
Using-Python-Libraries.9485146.powerpoint.pptxUsing-Python-Libraries.9485146.powerpoint.pptx
Using-Python-Libraries.9485146.powerpoint.pptxUadAccount
Ā 

Similar to Elegant Solutions for Everyday Python Problems Pycon 2018 - Nina Zakharenko (20)

Elegant Solutions For Everyday Python Problems - PyCon Canada 2017
Elegant Solutions For Everyday Python Problems - PyCon Canada 2017Elegant Solutions For Everyday Python Problems - PyCon Canada 2017
Elegant Solutions For Everyday Python Problems - PyCon Canada 2017
Ā 
Elegant Solutions For Everyday Python Problems - Nina Zakharenko
Elegant Solutions For Everyday Python Problems - Nina ZakharenkoElegant Solutions For Everyday Python Problems - Nina Zakharenko
Elegant Solutions For Everyday Python Problems - Nina Zakharenko
Ā 
Python na Infraestrutura ā€ØMySQL do Facebookā€Ø
Python na Infraestrutura ā€ØMySQL do Facebookā€ØPython na Infraestrutura ā€ØMySQL do Facebookā€Ø
Python na Infraestrutura ā€ØMySQL do Facebookā€Ø
Ā 
Python_UNIT-I.pptx
Python_UNIT-I.pptxPython_UNIT-I.pptx
Python_UNIT-I.pptx
Ā 
Iterarators and generators in python
Iterarators and generators in pythonIterarators and generators in python
Iterarators and generators in python
Ā 
python ppt.pptx
python ppt.pptxpython ppt.pptx
python ppt.pptx
Ā 
Advance python
Advance pythonAdvance python
Advance python
Ā 
Functions2.pptx
Functions2.pptxFunctions2.pptx
Functions2.pptx
Ā 
C++ code, please help! RESPOND W COMPLETED CODE PLEASE, am using V.pdf
C++ code, please help! RESPOND W COMPLETED CODE PLEASE,  am using V.pdfC++ code, please help! RESPOND W COMPLETED CODE PLEASE,  am using V.pdf
C++ code, please help! RESPOND W COMPLETED CODE PLEASE, am using V.pdf
Ā 
Python lecture 03
Python lecture 03Python lecture 03
Python lecture 03
Ā 
Cc code cards
Cc code cardsCc code cards
Cc code cards
Ā 
Python_Functions_Unit1.pptx
Python_Functions_Unit1.pptxPython_Functions_Unit1.pptx
Python_Functions_Unit1.pptx
Ā 
Introduction to python programming 2
Introduction to python programming   2Introduction to python programming   2
Introduction to python programming 2
Ā 
Pythonlearn-04-Functions (1).pptx
Pythonlearn-04-Functions (1).pptxPythonlearn-04-Functions (1).pptx
Pythonlearn-04-Functions (1).pptx
Ā 
Functions_19_20.pdf
Functions_19_20.pdfFunctions_19_20.pdf
Functions_19_20.pdf
Ā 
C++ Course - Lesson 2
C++ Course - Lesson 2C++ Course - Lesson 2
C++ Course - Lesson 2
Ā 
Advanced Web Technology ass.pdf
Advanced Web Technology ass.pdfAdvanced Web Technology ass.pdf
Advanced Web Technology ass.pdf
Ā 
Functions2.pdf
Functions2.pdfFunctions2.pdf
Functions2.pdf
Ā 
Generators & Decorators.pptx
Generators & Decorators.pptxGenerators & Decorators.pptx
Generators & Decorators.pptx
Ā 
Using-Python-Libraries.9485146.powerpoint.pptx
Using-Python-Libraries.9485146.powerpoint.pptxUsing-Python-Libraries.9485146.powerpoint.pptx
Using-Python-Libraries.9485146.powerpoint.pptx
Ā 

More from Nina Zakharenko

Recovering From Git Mistakes - Nina Zakharenko
Recovering From Git Mistakes - Nina ZakharenkoRecovering From Git Mistakes - Nina Zakharenko
Recovering From Git Mistakes - Nina ZakharenkoNina Zakharenko
Ā 
Code Review Skills for Pythonistas - Nina Zakharenko - EuroPython
Code Review Skills for Pythonistas - Nina Zakharenko - EuroPythonCode Review Skills for Pythonistas - Nina Zakharenko - EuroPython
Code Review Skills for Pythonistas - Nina Zakharenko - EuroPythonNina Zakharenko
Ā 
How to successfully grow a code review culture
How to successfully grow a code review cultureHow to successfully grow a code review culture
How to successfully grow a code review cultureNina Zakharenko
Ā 
Memory Management In Python The Basics
Memory Management In Python The BasicsMemory Management In Python The Basics
Memory Management In Python The BasicsNina Zakharenko
Ā 
Djangocon 2014 - Django REST Framework - So Easy You Can Learn it in 25 Minutes
Djangocon 2014 - Django REST Framework - So Easy You Can Learn it in 25 MinutesDjangocon 2014 - Django REST Framework - So Easy You Can Learn it in 25 Minutes
Djangocon 2014 - Django REST Framework - So Easy You Can Learn it in 25 MinutesNina Zakharenko
Ā 
Nina Zakharenko - Introduction to Git - Start SLC 2015
Nina Zakharenko - Introduction to Git - Start SLC 2015Nina Zakharenko - Introduction to Git - Start SLC 2015
Nina Zakharenko - Introduction to Git - Start SLC 2015Nina Zakharenko
Ā 
Djangocon 2014 angular + django
Djangocon 2014 angular + djangoDjangocon 2014 angular + django
Djangocon 2014 angular + djangoNina Zakharenko
Ā 

More from Nina Zakharenko (7)

Recovering From Git Mistakes - Nina Zakharenko
Recovering From Git Mistakes - Nina ZakharenkoRecovering From Git Mistakes - Nina Zakharenko
Recovering From Git Mistakes - Nina Zakharenko
Ā 
Code Review Skills for Pythonistas - Nina Zakharenko - EuroPython
Code Review Skills for Pythonistas - Nina Zakharenko - EuroPythonCode Review Skills for Pythonistas - Nina Zakharenko - EuroPython
Code Review Skills for Pythonistas - Nina Zakharenko - EuroPython
Ā 
How to successfully grow a code review culture
How to successfully grow a code review cultureHow to successfully grow a code review culture
How to successfully grow a code review culture
Ā 
Memory Management In Python The Basics
Memory Management In Python The BasicsMemory Management In Python The Basics
Memory Management In Python The Basics
Ā 
Djangocon 2014 - Django REST Framework - So Easy You Can Learn it in 25 Minutes
Djangocon 2014 - Django REST Framework - So Easy You Can Learn it in 25 MinutesDjangocon 2014 - Django REST Framework - So Easy You Can Learn it in 25 Minutes
Djangocon 2014 - Django REST Framework - So Easy You Can Learn it in 25 Minutes
Ā 
Nina Zakharenko - Introduction to Git - Start SLC 2015
Nina Zakharenko - Introduction to Git - Start SLC 2015Nina Zakharenko - Introduction to Git - Start SLC 2015
Nina Zakharenko - Introduction to Git - Start SLC 2015
Ā 
Djangocon 2014 angular + django
Djangocon 2014 angular + djangoDjangocon 2014 angular + django
Djangocon 2014 angular + django
Ā 

Recently uploaded

ć€Žę¾³ę“²ę–‡å‡­ć€ä¹°éŗ¦č€ƒē‘žå¤§å­¦ęƕäøščÆä¹¦ęˆē»©å•åŠžē†ę¾³ę“²Macquarieę–‡å‡­å­¦ä½čƁ书
ć€Žę¾³ę“²ę–‡å‡­ć€ä¹°éŗ¦č€ƒē‘žå¤§å­¦ęƕäøščÆä¹¦ęˆē»©å•åŠžē†ę¾³ę“²Macquarieę–‡å‡­å­¦ä½čÆä¹¦ć€Žę¾³ę“²ę–‡å‡­ć€ä¹°éŗ¦č€ƒē‘žå¤§å­¦ęƕäøščÆä¹¦ęˆē»©å•åŠžē†ę¾³ę“²Macquarieę–‡å‡­å­¦ä½čƁ书
ć€Žę¾³ę“²ę–‡å‡­ć€ä¹°éŗ¦č€ƒē‘žå¤§å­¦ęƕäøščÆä¹¦ęˆē»©å•åŠžē†ę¾³ę“²Macquarieę–‡å‡­å­¦ä½čƁ书rnrncn29
Ā 
Module-1-(Building Acoustics) Noise Control (Unit-3). pdf
Module-1-(Building Acoustics) Noise Control (Unit-3). pdfModule-1-(Building Acoustics) Noise Control (Unit-3). pdf
Module-1-(Building Acoustics) Noise Control (Unit-3). pdfManish Kumar
Ā 
Energy Awareness training ppt for manufacturing process.pptx
Energy Awareness training ppt for manufacturing process.pptxEnergy Awareness training ppt for manufacturing process.pptx
Energy Awareness training ppt for manufacturing process.pptxsiddharthjain2303
Ā 
Ch10-Global Supply Chain - Cadena de Suministro.pdf
Ch10-Global Supply Chain - Cadena de Suministro.pdfCh10-Global Supply Chain - Cadena de Suministro.pdf
Ch10-Global Supply Chain - Cadena de Suministro.pdfChristianCDAM
Ā 
TEST CASE GENERATION GENERATION BLOCK BOX APPROACH
TEST CASE GENERATION GENERATION BLOCK BOX APPROACHTEST CASE GENERATION GENERATION BLOCK BOX APPROACH
TEST CASE GENERATION GENERATION BLOCK BOX APPROACHSneha Padhiar
Ā 
Computer Graphics Introduction, Open GL, Line and Circle drawing algorithm
Computer Graphics Introduction, Open GL, Line and Circle drawing algorithmComputer Graphics Introduction, Open GL, Line and Circle drawing algorithm
Computer Graphics Introduction, Open GL, Line and Circle drawing algorithmDeepika Walanjkar
Ā 
Comparative study of High-rise Building Using ETABS,SAP200 and SAFE., SAFE an...
Comparative study of High-rise Building Using ETABS,SAP200 and SAFE., SAFE an...Comparative study of High-rise Building Using ETABS,SAP200 and SAFE., SAFE an...
Comparative study of High-rise Building Using ETABS,SAP200 and SAFE., SAFE an...Erbil Polytechnic University
Ā 
Earthing details of Electrical Substation
Earthing details of Electrical SubstationEarthing details of Electrical Substation
Earthing details of Electrical Substationstephanwindworld
Ā 
List of Accredited Concrete Batching Plant.pdf
List of Accredited Concrete Batching Plant.pdfList of Accredited Concrete Batching Plant.pdf
List of Accredited Concrete Batching Plant.pdfisabel213075
Ā 
Turn leadership mistakes into a better future.pptx
Turn leadership mistakes into a better future.pptxTurn leadership mistakes into a better future.pptx
Turn leadership mistakes into a better future.pptxStephen Sitton
Ā 
TechTACĀ® CFD Report Summary: A Comparison of Two Types of Tubing Anchor Catchers
TechTACĀ® CFD Report Summary: A Comparison of Two Types of Tubing Anchor CatchersTechTACĀ® CFD Report Summary: A Comparison of Two Types of Tubing Anchor Catchers
TechTACĀ® CFD Report Summary: A Comparison of Two Types of Tubing Anchor Catcherssdickerson1
Ā 
CME 397 - SURFACE ENGINEERING - UNIT 1 FULL NOTES
CME 397 - SURFACE ENGINEERING - UNIT 1 FULL NOTESCME 397 - SURFACE ENGINEERING - UNIT 1 FULL NOTES
CME 397 - SURFACE ENGINEERING - UNIT 1 FULL NOTESkarthi keyan
Ā 
High Voltage Engineering- OVER VOLTAGES IN ELECTRICAL POWER SYSTEMS
High Voltage Engineering- OVER VOLTAGES IN ELECTRICAL POWER SYSTEMSHigh Voltage Engineering- OVER VOLTAGES IN ELECTRICAL POWER SYSTEMS
High Voltage Engineering- OVER VOLTAGES IN ELECTRICAL POWER SYSTEMSsandhya757531
Ā 
"Exploring the Essential Functions and Design Considerations of Spillways in ...
"Exploring the Essential Functions and Design Considerations of Spillways in ..."Exploring the Essential Functions and Design Considerations of Spillways in ...
"Exploring the Essential Functions and Design Considerations of Spillways in ...Erbil Polytechnic University
Ā 
FUNCTIONAL AND NON FUNCTIONAL REQUIREMENT
FUNCTIONAL AND NON FUNCTIONAL REQUIREMENTFUNCTIONAL AND NON FUNCTIONAL REQUIREMENT
FUNCTIONAL AND NON FUNCTIONAL REQUIREMENTSneha Padhiar
Ā 
Mine Environment II Lab_MI10448MI__________.pptx
Mine Environment II Lab_MI10448MI__________.pptxMine Environment II Lab_MI10448MI__________.pptx
Mine Environment II Lab_MI10448MI__________.pptxRomil Mishra
Ā 
Levelling - Rise and fall - Height of instrument method
Levelling - Rise and fall - Height of instrument methodLevelling - Rise and fall - Height of instrument method
Levelling - Rise and fall - Height of instrument methodManicka Mamallan Andavar
Ā 
Gravity concentration_MI20612MI_________
Gravity concentration_MI20612MI_________Gravity concentration_MI20612MI_________
Gravity concentration_MI20612MI_________Romil Mishra
Ā 
signals in triangulation .. ...Surveying
signals in triangulation .. ...Surveyingsignals in triangulation .. ...Surveying
signals in triangulation .. ...Surveyingsapna80328
Ā 
Immutable Image-Based Operating Systems - EW2024.pdf
Immutable Image-Based Operating Systems - EW2024.pdfImmutable Image-Based Operating Systems - EW2024.pdf
Immutable Image-Based Operating Systems - EW2024.pdfDrew Moseley
Ā 

Recently uploaded (20)

ć€Žę¾³ę“²ę–‡å‡­ć€ä¹°éŗ¦č€ƒē‘žå¤§å­¦ęƕäøščÆä¹¦ęˆē»©å•åŠžē†ę¾³ę“²Macquarieę–‡å‡­å­¦ä½čƁ书
ć€Žę¾³ę“²ę–‡å‡­ć€ä¹°éŗ¦č€ƒē‘žå¤§å­¦ęƕäøščÆä¹¦ęˆē»©å•åŠžē†ę¾³ę“²Macquarieę–‡å‡­å­¦ä½čÆä¹¦ć€Žę¾³ę“²ę–‡å‡­ć€ä¹°éŗ¦č€ƒē‘žå¤§å­¦ęƕäøščÆä¹¦ęˆē»©å•åŠžē†ę¾³ę“²Macquarieę–‡å‡­å­¦ä½čƁ书
ć€Žę¾³ę“²ę–‡å‡­ć€ä¹°éŗ¦č€ƒē‘žå¤§å­¦ęƕäøščÆä¹¦ęˆē»©å•åŠžē†ę¾³ę“²Macquarieę–‡å‡­å­¦ä½čƁ书
Ā 
Module-1-(Building Acoustics) Noise Control (Unit-3). pdf
Module-1-(Building Acoustics) Noise Control (Unit-3). pdfModule-1-(Building Acoustics) Noise Control (Unit-3). pdf
Module-1-(Building Acoustics) Noise Control (Unit-3). pdf
Ā 
Energy Awareness training ppt for manufacturing process.pptx
Energy Awareness training ppt for manufacturing process.pptxEnergy Awareness training ppt for manufacturing process.pptx
Energy Awareness training ppt for manufacturing process.pptx
Ā 
Ch10-Global Supply Chain - Cadena de Suministro.pdf
Ch10-Global Supply Chain - Cadena de Suministro.pdfCh10-Global Supply Chain - Cadena de Suministro.pdf
Ch10-Global Supply Chain - Cadena de Suministro.pdf
Ā 
TEST CASE GENERATION GENERATION BLOCK BOX APPROACH
TEST CASE GENERATION GENERATION BLOCK BOX APPROACHTEST CASE GENERATION GENERATION BLOCK BOX APPROACH
TEST CASE GENERATION GENERATION BLOCK BOX APPROACH
Ā 
Computer Graphics Introduction, Open GL, Line and Circle drawing algorithm
Computer Graphics Introduction, Open GL, Line and Circle drawing algorithmComputer Graphics Introduction, Open GL, Line and Circle drawing algorithm
Computer Graphics Introduction, Open GL, Line and Circle drawing algorithm
Ā 
Comparative study of High-rise Building Using ETABS,SAP200 and SAFE., SAFE an...
Comparative study of High-rise Building Using ETABS,SAP200 and SAFE., SAFE an...Comparative study of High-rise Building Using ETABS,SAP200 and SAFE., SAFE an...
Comparative study of High-rise Building Using ETABS,SAP200 and SAFE., SAFE an...
Ā 
Earthing details of Electrical Substation
Earthing details of Electrical SubstationEarthing details of Electrical Substation
Earthing details of Electrical Substation
Ā 
List of Accredited Concrete Batching Plant.pdf
List of Accredited Concrete Batching Plant.pdfList of Accredited Concrete Batching Plant.pdf
List of Accredited Concrete Batching Plant.pdf
Ā 
Turn leadership mistakes into a better future.pptx
Turn leadership mistakes into a better future.pptxTurn leadership mistakes into a better future.pptx
Turn leadership mistakes into a better future.pptx
Ā 
TechTACĀ® CFD Report Summary: A Comparison of Two Types of Tubing Anchor Catchers
TechTACĀ® CFD Report Summary: A Comparison of Two Types of Tubing Anchor CatchersTechTACĀ® CFD Report Summary: A Comparison of Two Types of Tubing Anchor Catchers
TechTACĀ® CFD Report Summary: A Comparison of Two Types of Tubing Anchor Catchers
Ā 
CME 397 - SURFACE ENGINEERING - UNIT 1 FULL NOTES
CME 397 - SURFACE ENGINEERING - UNIT 1 FULL NOTESCME 397 - SURFACE ENGINEERING - UNIT 1 FULL NOTES
CME 397 - SURFACE ENGINEERING - UNIT 1 FULL NOTES
Ā 
High Voltage Engineering- OVER VOLTAGES IN ELECTRICAL POWER SYSTEMS
High Voltage Engineering- OVER VOLTAGES IN ELECTRICAL POWER SYSTEMSHigh Voltage Engineering- OVER VOLTAGES IN ELECTRICAL POWER SYSTEMS
High Voltage Engineering- OVER VOLTAGES IN ELECTRICAL POWER SYSTEMS
Ā 
"Exploring the Essential Functions and Design Considerations of Spillways in ...
"Exploring the Essential Functions and Design Considerations of Spillways in ..."Exploring the Essential Functions and Design Considerations of Spillways in ...
"Exploring the Essential Functions and Design Considerations of Spillways in ...
Ā 
FUNCTIONAL AND NON FUNCTIONAL REQUIREMENT
FUNCTIONAL AND NON FUNCTIONAL REQUIREMENTFUNCTIONAL AND NON FUNCTIONAL REQUIREMENT
FUNCTIONAL AND NON FUNCTIONAL REQUIREMENT
Ā 
Mine Environment II Lab_MI10448MI__________.pptx
Mine Environment II Lab_MI10448MI__________.pptxMine Environment II Lab_MI10448MI__________.pptx
Mine Environment II Lab_MI10448MI__________.pptx
Ā 
Levelling - Rise and fall - Height of instrument method
Levelling - Rise and fall - Height of instrument methodLevelling - Rise and fall - Height of instrument method
Levelling - Rise and fall - Height of instrument method
Ā 
Gravity concentration_MI20612MI_________
Gravity concentration_MI20612MI_________Gravity concentration_MI20612MI_________
Gravity concentration_MI20612MI_________
Ā 
signals in triangulation .. ...Surveying
signals in triangulation .. ...Surveyingsignals in triangulation .. ...Surveying
signals in triangulation .. ...Surveying
Ā 
Immutable Image-Based Operating Systems - EW2024.pdf
Immutable Image-Based Operating Systems - EW2024.pdfImmutable Image-Based Operating Systems - EW2024.pdf
Immutable Image-Based Operating Systems - EW2024.pdf
Ā 

Elegant Solutions for Everyday Python Problems Pycon 2018 - Nina Zakharenko

  • 2. slides: h!p://bit.ly/elegant-python This talk is for you if: You're an intermediate python programmer You're coming to python from another language You want to learn about language features like: magic methods, iterators, decorators, and context managers @nnja
  • 4. How do we make code elegant? We pick the right tool for the job! Resources for converting from Python 2 -> 3
  • 5. Beauty is in the eye of the beholder
  • 7. Magic methods start and end with a double underscore (dunder) By implementing a few straightforward magic methods, you can make your objects behave like built-ins such as: numbers lists dictionaries and more... @nnja
  • 8. class Money: currency_rates = { '$': 1, 'ā‚¬': 0.88, } def __init__(self, symbol, amount): self.symbol = symbol self.amount = amount def __str__(self): return '%s%.2f' % (self.symbol, self.amount) @nnja
  • 9. class Money: currency_rates = { '$': 1, 'ā‚¬': 0.88, } def __init__(self, symbol, amount): self.symbol = symbol self.amount = amount def __str__(self): return '%s%.2f' % (self.symbol, self.amount) @nnja
  • 10. class Money: # deļ¬ned currency_rates, __init__, and str above... def convert(self, other): """Convert other amount to our currency""" new_amount = ( other.amount / self.currency_rates[other.symbol] * self.currency_rates[self.symbol]) return Money(self.symbol, new_amount) @nnja
  • 11. __str__ in action >>> soda_cost = Money('$', 5.25) >>> print(soda_cost) $5.25 >>> pizza_cost = Money('ā‚¬', 7.99) >>> print(pizza_cost) ā‚¬7.99 @nnja
  • 12. class Money: def __add__(self, other): """ Add 2 Money instances using '+' """ new_amount = self.amount + self.convert(other).amount return Money(self.symbol, new_amount) @nnja
  • 13. >>> soda_cost = Money('$', 5.25) >>> pizza_cost = Money('ā‚¬', 7.99) >>> print(soda_cost + pizza_cost) $14.33 More on Magic Methods: Dive into Python3 - Special Method Names
  • 14. >>> soda_cost = Money('$', 5.25) >>> pizza_cost = Money('ā‚¬', 7.99) >>> print(soda_cost + pizza_cost) $14.33 >>> print(pizza_cost + soda_cost) ā‚¬12.61 More on Magic Methods: Dive into Python3 - Special Method Names
  • 15. some magic methods map to symbols >>> d = {'one': 1, 'two': 2} >>> d['two'] 2 >>> d.__getitem__('two') 2 @nnja
  • 16. other magic methods map to built-in functions class SquareShape: def __len__(self): """ Return the number of sides in our shape """ return 4 >>> my_square = SquareShape() >>> len(my_square) 4 @nnja
  • 18. Making classes iterable In order to be iterable, a class needs to implement __iter__() __iter__() must return an iterator In order to be an iterator a class needs to implement __next__() which must raise StopIteration when there are no more items to return Great explanation of iterable vs. iterator vs. generator
  • 19. Scenario.. We have a Server instance running services on different ports. Some services are active, some are inactive. When we loop over our the Server instance, we only want to loop over active services. @nnja
  • 20. class IterableServer: services = [ {'active': False, 'protocol': 'ftp', 'port': 21}, {'active': True, 'protocol': 'ssh', 'port': 22}, {'active': True, 'protocol': 'http', 'port': 80}, ] @nnja
  • 21. class IterableServer: def __init__(self): self.current_pos = 0 def __iter__(self): # can return self, because __next__ implemented return self def __next__(self): while self.current_pos < len(self.services): service = self.services[self.current_pos] self.current_pos += 1 if service['active']: return service['protocol'], service['port'] raise StopIteration @nnja
  • 22. class IterableServer: def __init__(self): self.current_pos = 0 def __iter__(self): # can return self, because __next__ implemented return self def __next__(self): while self.current_pos < len(self.services): service = self.services[self.current_pos] self.current_pos += 1 if service['active']: return service['protocol'], service['port'] raise StopIteration @nnja
  • 23. >>> for protocol, port in IterableServer(): print('service %s on port %d' % (protocol, port)) service ssh on port 22 service http on port 80 loops over all active services ... not bad @nnja
  • 24. tip: use a generator when your iterator doesn't need to maintain a lot of state (which is most of the time) @nnja
  • 25. class Server: services = [ {'active': False, 'protocol': 'ftp', 'port': 21}, {'active': True, 'protocol': 'ssh', 'port': 22}, {'active': True, 'protocol': 'http', 'port': 21}, ] def __iter__(self): for service in self.services: if service['active']: yield service['protocol'], service['port'] @nnja
  • 26. class Server: services = [ {'active': False, 'protocol': 'ftp', 'port': 21}, {'active': True, 'protocol': 'ssh', 'port': 22}, {'active': True, 'protocol': 'http', 'port': 21}, ] def __iter__(self): for service in self.services: if service['active']: yield service['protocol'], service['port'] @nnja
  • 27. Why does this work? use single parenthesis ( ) to create a generator comprehension ^ technically, a generator expression but I like this term better, and so does Ned Batchelder >>> my_gen = (num for num in range(1)) >>> my_gen <generator object <genexpr> at 0x107581bf8> @nnja
  • 28. An iterator must implement __next__() >>> next(my_gen) # __next__() maps to built-in next() 0 and raise StopIteration when there are no more elements >>> next(my_gen) ... StopIteration Traceback (most recent call last) see itertools for working with iterators
  • 30. alias methods class Word: def __init__(self, word): self.word = word def __repr__(self): return self.word def __add__(self, other_word): return Word('%s %s' % (self.word, other_word)) # Add an alias from method __add__ to the method concat concat = __add__ @nnja
  • 31. We can add an alias from __add__ to concat because methods are just objects >>> # remember, concat = __add__ >>> ļ¬rst_name = Word('Max') >>> last_name = Word('Smith') >>> ļ¬rst_name + last_name Max Smith >>> ļ¬rst_name.concat(last_name) Max Smith >>> Word.__add__ == Word.concat True @nnja
  • 32. Dog class >>> class Dog: sound = 'Bark' def speak(self): print(self.sound + '!', self.sound + '!') >>> my_dog = Dog() >>> my_dog.speak() Bark! Bark! read the docs
  • 33. getattr(object, name, default) >>> class Dog: sound = 'Bark' def speak(self): print(self.sound + '!', self.sound + '!') >>> my_dog = Dog() >>> my_dog.speak() Bark! Bark! >>> getattr(my_dog, 'speak') <bound method Dog.speak of <__main__.Dog object at 0x10b145f28>> >>> speak_method = getattr(my_dog, 'speak') >>> speak_method() Bark! Bark!
  • 34. getattr(object, name, default) >>> class Dog: sound = 'Bark' def speak(self): print(self.sound + '!', self.sound + '!') >>> my_dog = Dog() >>> my_dog.speak() Bark! Bark! >>> getattr(my_dog, 'speak') <bound method Dog.speak of <__main__.Dog object at 0x10b145f28>> >>> speak_method = getattr(my_dog, 'speak') >>> speak_method() Bark! Bark!
  • 35. Example: command line tool with dynamic commands class Operations: def say_hi(self, name): print('Hello,', name) def say_bye(self, name): print('Goodbye,', name) def default(self, arg): print('This operation is not supported.') if __name__ == '__main__': operations = Operations() # let's assume error handling command, argument = input('> ').split() getattr(operations, command, operations.default)(argument) read the docs
  • 36. Output $ python demo.py > say_hi Nina Hello, Nina > blah blah This operation is not supported. āœØ additional reading - inverse of getattr() is setattr()
  • 37. functools.partial(func, *args, **kwargs) Return a new partial object which behaves like func called with args & kwargs if more arguments are passed in, they are appended to args if more keyword arguments are passed in, they extend and override kwargs read the docs on partials
  • 38. functool.partial(func, *args, **kwargs) # We want to be able to call this function on any int # without having to specify the base. >>> int('10010', base=2) 18 >>> from functools import partial >>> basetwo = partial(int, base=2) >>> basetwo <functools.partial object at 0x1085a09f0> >>> basetwo('10010') 18 read the docs on partials
  • 39. functool.partial(func, *args, **kwargs) # We want to be able to call this function on any int # without having to specify the base. >>> int('10010', base=2) 18 >>> from functools import partial >>> basetwo = partial(int, base=2) >>> basetwo <functools.partial object at 0x1085a09f0> >>> basetwo('10010') 18 read the docs on partials
  • 40. functool.partial(func, *args, **kwargs) # We want to be able to call this function on any int # without having to specify the base. >>> int('10010', base=2) 18 >>> from functools import partial >>> basetwo = partial(int, base=2) >>> basetwo <functools.partial object at 0x1085a09f0> >>> basetwo('10010') 18 read the docs on partials
  • 41. magic methods & method magic in action! photo credit
  • 42. library I ! : github.com/mozilla/agithub agithub is a (poorly named) REST API client with transparent syntax which facilitates rapid prototyping ā€” on any REST API! Implemented in ~400 lines. Add support for any REST API in ~30 lines of code. agithub knows everything it needs to about protocol (REST, HTTP, etc), but assumes nothing about your upstream API. @nnja
  • 43. deļ¬ne endpoint url & other connection properties class GitHub(API): def __init__(self, token=None, *args, **kwargs): props = ConnectionProperties( api_url = kwargs.pop('api_url', 'api.github.com')) self.setClient(Client(*args, **kwargs)) self.setConnectionProperties(props) @nnja
  • 44. then, start using the API! >>> gh = GitHub('token') >>> status, data = gh.user.repos.get() >>> # ^ Maps to GET /user/repos >>> data ... ['tweeter', 'snipey', '...'] github.com/mozilla/agithub
  • 45. 404 if we provide a path that doesn't exist: >>> gh = GitHub('token') >>> status, data = gh.this.path.doesnt.exist.get() >>> status ... 404 github.com/jpaugh/agithub
  • 47. class API: def __getattr__(self, key): return IncompleteRequest(self.client).__getattr__(key) __getitem__ = __getattr__ class IncompleteRequest: def __getattr__(self, key): if key in self.client.http_methods: htmlMethod = getattr(self.client, key) return partial(htmlMethod, url=self.url) else: self.url += '/' + str(key) return self __getitem__ = __getattr__ class Client: http_methods = ('get') # ... def get(self, url, headers={}, **params): return self.request('GET', url, None, headers) github.com/jpaugh/agithub source: base.py
  • 48. class API: def __getattr__(self, key): return IncompleteRequest(self.client).__getattr__(key) __getitem__ = __getattr__ class IncompleteRequest: def __getattr__(self, key): if key in self.client.http_methods: htmlMethod = getattr(self.client, key) return partial(htmlMethod, url=self.url) else: self.url += '/' + str(key) return self __getitem__ = __getattr__ class Client: http_methods = ('get') # ... def get(self, url, headers={}, **params): return self.request('GET', url, None, headers) github.com/jpaugh/agithub source: base.py
  • 49. class API: def __getattr__(self, key): return IncompleteRequest(self.client).__getattr__(key) __getitem__ = __getattr__ class IncompleteRequest: def __getattr__(self, key): if key in self.client.http_methods: htmlMethod = getattr(self.client, key) return partial(htmlMethod, url=self.url) else: self.url += '/' + str(key) return self __getitem__ = __getattr__ class Client: http_methods = ('get') # ... def get(self, url, headers={}, **params): return self.request('GET', url, None, headers) github.com/jpaugh/agithub source: base.py
  • 51. When should I use one? Need to perform an action before and/or after an operation. Common scenarios: Closing a resource after you're done with it (ļ¬le, network connection) Perform cleanup before/after a function call @nnja
  • 52. Example Problem: Feature Flags Turn features of your application on and off easily. Uses of feature ļ¬‚ags: A/B Testing Rolling Releases Show Beta version to users opted-in to Beta Testing Program More on Feature Flags
  • 53. class FeatureFlags: SHOW_BETA = 'Show Beta version of Home Page' ļ¬‚ags = { SHOW_BETA: True } @classmethod def is_on(cls, name): return cls.ļ¬‚ags[name] @classmethod def toggle(cls, name, value): cls.ļ¬‚ags[name] = value feature_ļ¬‚ags = FeatureFlags() @nnja
  • 54. How do we temporarily turn features on and off when testing ļ¬‚ags? Want: with feature_ļ¬‚ag(FeatureFlags.SHOW_BETA): assert '/beta' == get_homepage_url() @nnja
  • 55. Using Magic Methods __enter__ and __exit__ class feature_ļ¬‚ag: """ Implementing a Context Manager using Magic Methods """ def __init__(self, name, on=True): self.name = name self.on = on self.old_value = feature_ļ¬‚ags.is_on(name) def __enter__(self): feature_ļ¬‚ags.toggle(self.name, self.on) def __exit__(self, *args): feature_ļ¬‚ags.toggle(self.name, self.old_value) See: contextlib.contextmanager
  • 56. The be!er way: using the contextmanager decorator from contextlib import contextmanager @contextmanager def feature_ļ¬‚ag(name, on=True): old_value = feature_ļ¬‚ags.is_on(name) feature_ļ¬‚ags.toggle(name, on) yield feature_ļ¬‚ags.toggle(name, old_value) See: contextlib.contextmanager
  • 57. The be!er way: using the contextmanager decorator from contextlib import contextmanager @contextmanager def feature_ļ¬‚ag(name, on=True): """ The easier way to create Context Managers """ old_value = feature_ļ¬‚ags.is_on(name) # behavior of __enter__() feature_ļ¬‚ags.toggle(name, on) yield # behavior of __exit__() feature_ļ¬‚ags.toggle(name, old_value) See: contextlib.contextmanager
  • 58. Note: yield? from contextlib import contextmanager @contextmanager def feature_ļ¬‚ag(name, on=True): """ The easier way to create Context Managers """ old_value = feature_ļ¬‚ags.is_on(name) feature_ļ¬‚ags.toggle(name, on) # behavior of __enter__() yield feature_ļ¬‚ags.toggle(name, old_value) # behavior of __exit__() See: contextlib.contextmanager
  • 59. either implementation def get_homepage_url(): """ Returns the path of the page to display """ if feature_ļ¬‚ags.is_on(FeatureFlags.SHOW_BETA): return '/beta' else: return '/homepage' def test_homepage_url_with_context_manager(): with feature_ļ¬‚ag(FeatureFlags.SHOW_BETA): # saw the beta homepage... assert get_homepage_url() == '/beta' with feature_ļ¬‚ag(FeatureFlags.SHOW_BETA, on=False): # saw the standard homepage... assert get_homepage_url() == '/homepage'
  • 60. either implementation def get_homepage_url(): """ Returns the path of the page to display """ if feature_ļ¬‚ags.is_on(FeatureFlags.SHOW_BETA): return '/beta' else: return '/homepage' def test_homepage_url_with_context_manager(): with feature_ļ¬‚ag(FeatureFlags.SHOW_BETA): assert get_homepage_url() == '/beta' print('seeing the beta homepage...') with feature_ļ¬‚ag(FeatureFlags.SHOW_BETA, on=False): assert get_homepage_url() == '/homepage' print('seeing the standard homepage...')
  • 61. Decorators The simple explanation: Syntactic sugar that allows modiļ¬cation of an underlying function. @nnja
  • 62. Decorators: Wrap a function in another function. Do something: before the call after the call with provided arguments modify the return value or arguments @nnja
  • 63. class User: is_authenticated = False def __init__(self, name): self.name = name Throw an exception if trying to access data only for logged in users: def display_proļ¬le_page(user): """ Display proļ¬le page for logged in User """ if not user.is_authenticated: raise Exception('User must login.') print('Proļ¬le: %s' % user.name)
  • 64. def enforce_authentication(func): def wrapper(user): if not user.is_authenticated: raise Exception('User must login.') return func(user) return wrapper the important logic: def enforce_authentication(func): def wrapper(user): if not user.is_authenticated: raise Exception('User must login.') return func(user) return wrapper @nnja
  • 65. Using enforce_authentication without a decorator: enforce_authentication(display_proļ¬le_page)(some_user) Or, as a decorator: @enforce_authentication def display_proļ¬le_page(user): print('Proļ¬le: %s' % user.name) Now this raises an Exception if unauthenticated: user = User('nina') display_proļ¬le_page(nina)
  • 66. Problem: lost context using a decorator >>> display_proļ¬le_page.__name__ 'wrapper' >>>> display_proļ¬le_page.__doc__ # ... empty Solution: Use contextlib.wraps from contextlib import wraps def enforce_authentication(func): @wraps(func) def wrapper(user): # ... rest of the code
  • 69. By using ContextDecorator you can easily write classes that can be used both as decorators with @ and context managers with the with statement. ContextDecorator is used by contextmanager(), so you get this functionality automatically . Or, you can write a class that extends from ContextDecorator or uses ContextDecorator as a mixin, and implements __enter__, __exit__ and __call__ @nnja
  • 70. Remember @contextmanager from earlier? from contextlib import contextmanager @contextmanager def feature_ļ¬‚ag(name, on=True): old_value = feature_ļ¬‚ags.is_on(name) feature_ļ¬‚ags.toggle(name, on) yield feature_ļ¬‚ags.toggle(name, old_value) @nnja
  • 71. use it as a context manager with feature_ļ¬‚ag(FeatureFlags.SHOW_BETA): assert get_homepage_url() == '/beta' or use as a decorator @feature_ļ¬‚ag(FeatureFlags.SHOW_BETA, on=False) def get_proļ¬le_page(): beta_ļ¬‚ag_on = feature_ļ¬‚ags.is_on( FeatureFlags.SHOW_BETA) if beta_ļ¬‚ag_on: return 'beta.html' else: return 'proļ¬le.html'
  • 72. library I ! : freezegun lets your python tests ā‡ travel through time! ā‡ from freezegun import freeze_time # use it as a Context Manager def test(): with freeze_time("2012-01-14"): assert datetime.datetime.now() == datetime.datetime( 2012, 1, 14) assert datetime.datetime.now() != datetime.datetime(2012, 1, 14) # or a decorator @freeze_time("2012-01-14") def test(): assert datetime.datetime.now() == datetime.datetime(2012, 1, 14) read the source sometime, it's mind-bending!
  • 73. NamedTuple Useful when you need lightweight representations of data. Create tuple subclasses with named ļ¬elds. @nnja
  • 74. Example from collections import namedtuple CacheInfo = namedtuple( "CacheInfo", ["hits", "misses", "max_size", "curr_size"]) @nnja
  • 75. Giving NamedTuples default values RoutingRule = namedtuple( 'RoutingRule', ['preļ¬x', 'queue_name', 'wait_time'] ) (1) By specifying defaults RoutingRule.__new__.__defaults__ = (None, None, 20) (2) or with _replace to customize a prototype instance default_rule = RoutingRule(None, None, 20) user_rule = default_rule._replace( preļ¬x='user', queue_name='user-queue')
  • 76. NamedTuples can be subclassed and extended class Person(namedtuple('Person', ['ļ¬rst_name', 'last_name'])): """ Stores ļ¬rst and last name of a Person""" def __str__(self): return '%s %s' % (self.ļ¬rst_name, self.last_name) >>> me = Person('nina', 'zakharenko') >>> str(me) 'nina zakharenko' >>> me Person(ļ¬rst_name='nina', last_name='zakharenko')
  • 77. New Tools Magic Methods make your objects behave like builtins (numbers, list, dict, etc) Method ā‡Magicā‡ alias methods getattr @nnja
  • 78. ContextManagers Manage resources Decorators do something before/after call, modify return value or validate arguments ContextDecorators ContextManagers + Decorators in one @nnja
  • 79. Iterators & Generators Loop over your objects yield NamedTuple Lightweight classes @nnja
  • 80. "Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away." ā€” Antoine de Saint-Exupery @nnja