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

Python Decorators: An Intro

8145132ebae0c1f62cdd7b6126d71768?s=47 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.

8145132ebae0c1f62cdd7b6126d71768?s=128

Bill Israel

September 25, 2014
Tweet

More Decks by Bill Israel

Other Decks in Technology

Transcript

  1. @python.decorators pynash · september 25, 2014

  2. None
  3. @epochblue

  4. @epochblue

  5. 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
  6. @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
  7. A Quick Note

  8. 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())
  9. 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())
  10. But first...

  11. Let’s talk about functions

  12. def example():
 print("I'm a function!")

  13. >>> example() I'm a function! def example():
 print("I'm a function!")

  14. First-Class Functions

  15. Save functions into variables

  16. def example():
 print("I'm a function!")

  17. def example():
 print("I'm a function!") >>> f = example >>>

    f() I'm a function!
  18. Pass functions as arguments

  19. def example():
 print("I'm a function!")

  20. def example():
 print("I'm a function!") def first_class(func):
 func()

  21. def example():
 print("I'm a function!") >>> first_class(example) I'm a function!

    def first_class(func):
 func()
  22. Return functions from functions

  23. def example():
 print("I'm a function!")

  24. def example():
 print("I'm a function!") def first_class2():
 return example

  25. def example():
 print("I'm a function!") >>> f = first_class2() >>>

    f() I'm a function! def first_class2():
 return example
  26. Nest functions inside functions

  27. def fist_class3():
 msg = "I'm a function!"
 
 def example():


    print(msg)
 
 example()
  28. def fist_class3():
 msg = "I'm a function!"
 
 def example():


    print(msg)
 
 example() >>> first_class3() I'm a function!
  29. First-Class Functions

  30. Save functions into variables

  31. Return functions from functions Save functions into variables

  32. Pass functions as arguments Save functions into variables Return functions

    from functions
  33. Nest functions inside functions Save functions into variables Pass functions

    as arguments Return functions from functions
  34. Return functions from functions Pass functions as arguments Nest functions

    inside functions Save functions into variables
  35. Return functions from functions Pass functions as arguments Nest functions

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

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

    wrapper
 
 def example():
 print("I'm a function!")
  38. >>> 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!")
  39. >>> wrapped = decorator(example) >>> wrapped() I'm a wrapper. I'm

    a function!
  40. >>> example = decorator(example) >>> example() I'm a wrapper. I'm

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

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

    wrapper
 
 def example():
 print("I'm a function!") ! example = decorator(example)
  43. PEP 318

  44. example = decorator(example)

  45. example = decorator(example) example = decorator(example) @decorator
 def example():
 print("I'm

    a function!")
  46. 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())
  47. 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())
  48. 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
  49. @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
  50. @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
  51. 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
  52. 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
  53. @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
  54. @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
  55. Remember...

  56. @login_required
 def get_user_profile():
 # ... ...is the same as...

  57. get_user_profile = login_required(get_user_profile) @login_required
 def get_user_profile():
 # ... ...is the

    same as...
  58. @role_required('admin')
 def create_user():
 # ...

  59. @role_required('admin')
 def create_user():
 # ... ...is the same as...

  60. create_user = role_required('admin')(create_user) @role_required('admin')
 def create_user():
 # ... ...is the

    same as...
  61. create_user = role_required('admin')(create_user) @role_required('admin')
 def create_user():
 # ... OR ...is

    the same as...
  62. 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...
  63. 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
  64. 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
  65. 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
  66. @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
  67. @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
  68. @login_required
 @role_required('admin')
 def create_user(): # ... ...is the same as...

  69. @login_required
 @role_required('admin')
 def create_user(): # ... ...is the same as...

    create_user = login_required(role_required(‘admin’)(create_user))
  70. @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
  71. None
  72. @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
  73. @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
  74. @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
  75. from functools import wraps

  76. 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
  77. 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
  78. 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():
 # ...
  79. 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__
  80. 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’
  81. Recap

  82. 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
  83. 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
  84. 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
  85. @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
  86. None
  87. Decorators

  88. Questions? @epochblue Thank you.