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

Python Decorators: An Intro

Bill Israel
September 25, 2014

Python Decorators: An Intro

All the hip frameworks have them, you see them scattered around your codebase, but what IS a decorator? In this talk, Bill Israel will cover the features of Python that make decorators possible, how they work under the hood, what they're good for, and how you can start writing your own.

Bill Israel

September 25, 2014
Tweet

More Decks by Bill Israel

Other Decks in Technology

Transcript

  1. def get_user_profile():
 user_id = session.get('user_id')
 if user_id is None:
 return

    redirect('/login', code=302)
 
 user = users.get(user_id)
 return jsonify(user=user.to_json())
 
 
 def create_user():
 user_id = session.get('user_id')
 if user_id is None:
 return redirect('/login', code=302)
 
 user = users.get(session.get('user_id'))
 if not user.has_role('admin'):
 abort(401)
 
 data = request.get_json()
 new_user = users.create(**data)
 return jsonify(user=new_user.to_json()), 201
  2. @login_required
 def get_user_profile():
 user = users.get(session.get(‘user_id')
 return jsonify(user=user.to_json())
 
 


    @login_required
 @role_required('admin')
 def create_user():
 data = request.get_json()
 new_user = users.create(**data)
 return jsonify(user=new_user.to_json()), 201
  3. def get_user_profile():
 user_id = session.get('user_id')
 if user_id is None:
 return

    redirect('/login', code=302)
 
 user = users.get(user_id)
 return jsonify(user=user.to_json())
  4. def get_user_profile():
 user_id = session.get('user_id')
 if user_id is None:
 return

    redirect('/login', code=302)
 
 user = users.get(user_id)
 return jsonify(user=user.to_json())
  5. def example():
 print("I'm a function!") >>> f = first_class2() >>>

    f() I'm a function! def first_class2():
 return example
  6. def fist_class3():
 msg = "I'm a function!"
 
 def example():


    print(msg)
 
 example() >>> first_class3() I'm a function!
  7. Return functions from functions Pass functions as arguments Nest functions

    inside functions Save functions into variables Decorators
  8. def decorator(func):
 def wrapper():
 print("I'm a wrapper.")
 func()
 
 return

    wrapper
 
 def example():
 print("I'm a function!")
  9. def decorator(func):
 def wrapper():
 print("I'm a wrapper.")
 func()
 
 return

    wrapper
 
 def example():
 print("I'm a function!")
  10. >>> wrapped = decorator(example) >>> wrapped() I'm a wrapper. I'm

    a function! def decorator(func):
 def wrapper():
 print("I'm a wrapper.")
 func()
 
 return wrapper
 
 def example():
 print("I'm a function!")
  11. >>> example = decorator(example) >>> example() I'm a wrapper. I'm

    a function! >>> wrapped = decorator(example) >>> wrapped() I'm a wrapper. I'm a function!
  12. def decorator(f):
 def wrapper():
 print("I'm a wrapper.")
 f()
 
 return

    wrapper
 
 def example():
 print("I'm a function!") ! example = decorator(example)
  13. def decorator(f):
 def wrapper():
 print("I'm a wrapper.")
 f()
 
 return

    wrapper
 
 def example():
 print("I'm a function!") ! example = decorator(example)
  14. def get_user_profile():
 user_id = session.get('user_id')
 if user_id is None:
 return

    redirect('/login', code=302)
 
 user = users.get(user_id)
 return jsonify(user=user.to_json())
  15. def get_user_profile():
 user_id = session.get('user_id')
 if user_id is None:
 return

    redirect('/login', code=302)
 
 user = users.get(user_id)
 return jsonify(user=user.to_json())
  16. def login_required(func):
 def wrapper(*args, **kwargs):
 user_id = session.get('user_id')
 if user_id

    is None:
 return redirect('/login', code=302)
 
 return func(*args, **kwargs)
 
 return wrapper
  17. @login_required
 def get_user_profile():
 user = users.get(session.get('user_id'))
 return jsonify(user=user.to_json()) def login_required(func):


    def wrapper(*args, **kwargs):
 user_id = session.get('user_id')
 if user_id is None:
 return redirect('/login', code=302)
 
 return func(*args, **kwargs)
 
 return wrapper
  18. @login_required
 def get_user_profile():
 user = users.get(session.get('user_id'))
 return jsonify(user=user.to_json()) def login_required(func):


    def wrapper(*args, **kwargs):
 user_id = session.get('user_id')
 if user_id is None:
 return redirect('/login', code=302)
 
 return func(*args, **kwargs)
 
 return wrapper
  19. def create_new_user():
 user_id = session.get('user_id')
 if user_id is None:
 return

    redirect('/login', code=302)
 
 user = users.get(session.get('user_id'))
 if not user.has_role('admin'):
 abort(401)
 
 data = request.get_json()
 newbie = users.create(**data)
 return jsonify(user=newbie.to_json()), 201
  20. def create_new_user():
 user_id = session.get('user_id')
 if user_id is None:
 return

    redirect('/login', code=302)
 
 user = users.get(session.get('user_id'))
 if not user.has_role('admin'):
 abort(401)
 
 data = request.get_json()
 newbie = users.create(**data)
 return jsonify(user=newbie.to_json()), 201
  21. @login_required def create_new_user(): user = users.get(session.get('user_id'))
 if not user.has_role('admin'):
 abort(401)


    
 data = request.get_json()
 newbie = users.create(**data)
 return jsonify(user=newbie.to_json()), 201
  22. @login_required
 def create_new_user():
 user = users.get(session.get('user_id'))
 if not user.has_role('admin'):
 abort(401)


    
 data = request.get_json()
 newbie = users.create(**data)
 return jsonify(user=newbie.to_json()), 201
  23. create_user = role_required('admin')(create_user) @role_required('admin')
 def create_user():
 # ... OR decorator

    = role_required('admin')
 create_user = decorator(create_user) ...is the same as...
  24. def admin_required(func): 
 def wrapper(*args, **kwargs):
 user = users.get(session.get('user_id'))
 if

    not user.has_role('admin'):
 abort(401) 
 return func(*args, **kwargs)
 
 return wrapper
  25. def admin_required():
 def decorator(func): 
 def wrapper(*args, **kwargs):
 user =

    users.get(session.get('user_id'))
 if not user.has_role('admin'):
 abort(401) return func(*args, **kwargs) 
 return wrapper
 return decorator
  26. def role_required(role):
 def decorator(func): 
 def wrapper(*args, **kwargs):
 user =

    users.get(session.get('user_id'))
 if not user.has_role(role):
 abort(401)
 return func(*args, **kwargs) 
 return wrapper
 return decorator
  27. @role_required('admin')
 def create_user():
 data = request.get_json()
 new_user = users.create(**data)
 return

    jsonify(user=new_user.to_json()), 201 def role_required(role):
 def decorator(func): 
 def wrapper(*args, **kwargs):
 user = users.get(session.get('user_id'))
 if not user.has_role(role):
 abort(401)
 return func(*args, **kwargs) 
 return wrapper
 return decorator
  28. @login_required
 @role_required('admin')
 def create_user(): # ... ...is the same as...

    create_user = login_required(role_required(‘admin’)(create_user))
  29. @login_required
 def get_user_profile():
 # ... def login_required(func):
 def wrapper(*args, **kwargs):


    user_id = session.get('user_id')
 if user_id is None:
 return redirect('/login', code=302)
 
 return func(*args, **kwargs)
 
 return wrapper
  30. @login_required
 def get_user_profile():
 # ... >>> get_user_profile.__name__ def login_required(func):
 def

    wrapper(*args, **kwargs):
 user_id = session.get('user_id')
 if user_id is None:
 return redirect('/login', code=302)
 
 return func(*args, **kwargs)
 
 return wrapper
  31. @login_required
 def get_user_profile():
 # ... >>> get_user_profile.__name__ 'wrapper' def login_required(func):


    def wrapper(*args, **kwargs):
 user_id = session.get('user_id')
 if user_id is None:
 return redirect('/login', code=302)
 
 return func(*args, **kwargs)
 
 return wrapper
  32. def login_required(func):
 def wrapper(*args, **kwargs):
 user_id = session.get('user_id')
 if user_id

    is None:
 return redirect('/login', code=302)
 
 return func(*args, **kwargs)
 
 return wrapper
  33. from functools import wraps
 
 def login_required(func):
 @wraps(func)
 def wrapper(*args,

    **kwargs):
 user_id = session.get(user_id)
 if user_id is None:
 return redirect('/login', code=302)
 
 return func(*args, **kwargs)
 return wrapper
  34. from functools import wraps
 
 def login_required(func):
 @wraps(func)
 def wrapper(*args,

    **kwargs):
 user_id = session.get(user_id)
 if user_id is None:
 return redirect('/login', code=302)
 
 return func(*args, **kwargs)
 return wrapper @login_required
 def get_user_profile():
 # ...
  35. from functools import wraps
 
 def login_required(func):
 @wraps(func)
 def wrapper(*args,

    **kwargs):
 user_id = session.get(user_id)
 if user_id is None:
 return redirect('/login', code=302)
 
 return func(*args, **kwargs)
 return wrapper @login_required
 def get_user_profile():
 # ... >>> get_user_profile.__name__
  36. from functools import wraps
 
 def login_required(func):
 @wraps(func)
 def wrapper(*args,

    **kwargs):
 user_id = session.get(user_id)
 if user_id is None:
 return redirect('/login', code=302)
 
 return func(*args, **kwargs)
 return wrapper @login_required
 def get_user_profile():
 # ... >>> get_user_profile.__name__ ‘get_user_profile’
  37. def get_user_profile():
 user_id = session.get('user_id')
 if user_id is None:
 return

    redirect('/login', code=302)
 
 user = users.get(user_id)
 return jsonify(user=user.to_json())
 
 
 def create_user():
 user_id = session.get('user_id')
 if user_id is None:
 return redirect('/login', code=302)
 
 user = users.get(session.get('user_id'))
 if not user.has_role('admin'):
 abort(401)
 
 data = request.get_json()
 new_user = users.create(**data)
 return jsonify(user=new_user.to_json()), 201
  38. def get_user_profile():
 user_id = session.get('user_id')
 if user_id is None:
 return

    redirect('/login', code=302)
 
 user = users.get(user_id)
 return jsonify(user=user.to_json())
 
 
 def create_user():
 user_id = session.get('user_id')
 if user_id is None:
 return redirect('/login', code=302)
 
 user = users.get(g.get('user_id'))
 if not user.has_role('admin'):
 abort(401)
 
 data = request.get_json()
 new_user = users.create(**data)
 return jsonify(user=new_user.to_json()), 201
  39. def login_required(func):
 def wrapper(*args, **kwargs):
 user_id = session.get('user_id')
 if user_id

    is None:
 return redirect('/login', code=302)
 
 return func(*args, **kwargs)
 
 return wrapper def role_required(role):
 def decorator(func): 
 def wrapper(*args, **kwargs):
 user = users.get(session.get('user_id'))
 if not user.has_role(role):
 abort(401)
 return func(*args, **kwargs) 
 return wrapper
 return decorator
  40. @login_required
 def get_user_profile():
 user = users.get(session.get(‘user_id'))
 return jsonify(user=user.to_json())
 
 


    @login_required
 @role_required('admin')
 def create_user():
 data = request.get_json()
 new_user = users.create(**data)
 return jsonify(user=new_user.to_json()), 201