Python Decorators
Yiwei
Syntax Sugar
@some_decorator
def my_func(my_arg1, my_arg2):
......
def my_func(my_arg1, my_arg2):
......
my_func = some_decorator(my_func)
decorator: 一個吃 function 吐 function 的 function
def some_decorator(func):
def wrapper(a1, a2):
print('call '+func.__name__)
return func(a1, a2)
return wrapper
def my_func(my_arg1, my_arg2):
......
my_func = some_decorator(my_func)
大家可以回家啦 (?)
my_func = some_decorator(my_func) # WTF?
function 是一個「東西」
● 可以 assign
● 可以傳進另一個 function
● 可以定義在另一個 function,並回傳之
def f1(n):
print('I am f1')
sum = 0
for i in range(n+1):
sum += i
return sum
f2 = f1
def f1(n):
print('I am f1')
sum = 0
for i in range(n+1):
sum += i
return sum
f2 = f1
print('I am f1')
sum = 0
for i in range(n+1):
sum += i
return sum
f1f2
function 的定義
def f1(n):
print('I am f1')
sum = 0
for i in range(n+1):
sum += i
return sum
f2 = f1
f1 # <function f1 at 0x7f807e6261e0>
f2 # <function f1 at 0x7f807e6261e0>
f2(10) # 55
print('I am f1')
sum = 0
for i in range(n+1):
sum += i
return sum
f1f2
function 的定義
def f(number):
return number*10
def g(func, n):
return func(n)+8
# ⇧目前為止都只是定義,還沒被執行
g(f, 3) # 38
str_list.sort(key=str.lower)
注意不是 str.lower()
def f(number):
return number*10
def g(func, n):
return func(n)+8
# ⇧目前為止都只是定義,還沒被執行
g(f, 3) # 38
def gen_fat_checker(bmi):
bmi_bound = bmi
def f(w, h):
return w/(h*h) > bmi_bound
return f
fat = gen_fat_checker(20)
super_fat = gen_fat_checker(30)
print(fat(80.0, 1.7))
print(super_fat(80.0, 1.7))
def gen_fat_checker(bmi):
bmi_bound = bmi
return f
fat = gen_fat_checker(20) #只拿到函數本體
super_fat = gen_fat_checker(30) #還沒執行 f
print(fat(80.0, 1.7)) #現在才執行
print(super_fat(80.0, 1.7))
f = 敘述 function 要做什麼, 也敘述他吃2個參數
def gen_fat_checker(bmi):
bmi_bound = bmi
def f(w, h):
return w/(h*h) > bmi_bound
return f
def gen_fat_checker(bmi_bound):
def f(w, h):
return w/(h*h) > bmi_bound
return f
my_func = some_decorator(my_func)
function 是一個「東西」
● 可以 assign
● 可以傳進另一個 function
● 可以定義在另一個 function,並回傳之
知道了 function 是頭等公民...
decorator: 一個吃 function 吐 function 的 function
def some_decorator(func):
def wrapper(a1, a2):
print('call '+func.__name__)
return func(a1, a2)
return wrapper
def my_func(m1, m2):
print('{} {}'.format(m1, m2))
return m1 + m2
my_func = some_decorator(my_func)
my_func(5, 8)
Agenda
● Function as a “first-class citizen”
● Why decorator?
● 最簡單的 decorator
● 複雜一點的 decorator
Why decorator?
Query
def query_mysql(sql):
...
return result
res = query_mysql('select *')
Query with retry
def query_mysql(sql):
...
return result
for i in range(5):
try:
res = query_mysql('select *')
except:
sleep(60)
Download with retry
def download_s3(path):
...
return result
for i in range(5):
try:
res = download_s3('s3://a.csv')
except:
sleep(60)
XXXXX with retry
def find_mongo(q):
...
return result
for i in range(5):
try:
res = find_mongo('{f: 1}')
except:
sleep(60)
retry 吃 function (和其參數)
def retry(do_work, work_arg):
for i in range(5):
try:
return do_work(work_arg)
except:
sleep(60)
res = retry(query_mysql, 'select *')
retry 累贅,重點是執行 do_work(work_arg)
def retry(do_work, work_arg):
for i in range(5):
try:
work_res = do_work(work_arg)
return work_res
except:
sleep(60)
retry(query_mysql, 'select *')
retry(download_s3, 's3://a.csv')
retry(find_mongo, '{f: 1}')
重點是執行 do_work(work_arg)
def retry(do_work, work_arg):
for i in range(5):
try:
work_res = do_work(work_arg)
return work_res
except:
sleep(60)
retry(query_mysql, 'select *')
真的在執行
retry_query_mysql( 'select *')
可能寫成這樣嗎?
def retry(do_work) work_arg:
for i in range(5):
try:
work_res = do_work(work_arg)
return work_res
except:
sleep(60)
retry(query_mysql, 'select *')
真的在執行
retry(query_mysql)('select *')
可能寫成這樣嗎?
錯!
def retry(do_work):
def wrapper(work_arg):
for i in range(5):
try:
work_res = do_work(work_arg)
return work_res
except:
sleep(60)
return wrapper
retry(query_mysql)('select *')
只是定義:
吃一個arg的函數
一個吃 function 吐 function 的 function
def retry(do_work):
def wrapper(work_arg):
for i in range(5):
try:
work_res = do_work(work_arg)
return work_res
except:
sleep(60)
return wrapper
retry(query_mysql) #work is not executed
res = retry(query_mysql)('select *')
def retry(do_work):
def wrapper(work_arg):
for i in range(5):
try:
work_res = do_work(work_arg)
return work_res
except:
sleep(60)
return wrapper
res = retry(query_mysql)('select *')
def retry(do_work):
def wrapper(work_arg):
for i in range(5):
try:
work_res = do_work(work_arg)
return work_res
except:
sleep(60)
return wrapper
query_mysql = retry(query_mysql)
res = query_mysql('select *')
和這一個 section 第一頁的
呼叫法一樣了
decorator: syntax sugar
def retry(work):
def wrapper(work_arg):
work(work_arg)
return wrapper
def query_mysql(sql):
...
query_mysql = retry(query_mysql)
res = query_mysql('select *')
如果這 function 有一百行
就很難知道 query_mysql 被改了
def retry(work):
def wrapper(work_arg):
work(work_arg)
return wrapper
@retry
def query_mysql(sql):
...
res = query_mysql('select *')
Syntax Sugar
@decorator
def work():
......
def work():
......
work = decorator(work)
Syntax Sugar
@f2
@f1
def work():
......
def work():
......
work = f2(f1(work))
定義 vs. 使用
@measure_time
@cache
def work(w1):
......
def work(w1):
......
work = measure_time(
cache(
work))
r = work('123')
● 使用方式不變
● 擴充功能:
和黃金聖衣一樣
● 內在不變,但外在
變了
(你的work不是你的work)
def deco(work):
def wrapper(work_arg):
# TRICK BEFORE
work_res = work(work_arg)
# TRICK AFTER
return wrapper
● 根據 arg 來記住結果不執行 work (@lru_cache)
● 計時 work 花多久時間
● assert / verbose / logging
● @app.route(‘/get/<id>/’) 僅回傳 func 本身,同時也記起來
● @property
所以你應該會寫 decorator 給別人用了
def deco(work):
def _wrapper(work_arg):
return work(work_arg)
return _wrapper
def my_work(w1): @deco
... def my_work(w1):
my_work = deco(my_work) ...
res = my_work('123')
最簡單的 decorator
def retry(work):
def wrapper(work_arg):
for i in range(5):
try:
return work(work_arg)
except:
sleep(60)
return wrapper
@retry
def download(file1, file2):
...
事情不是憨人想得這麼簡單
@deco
def work(w1):
...
@deco
def work(w1, w2, w3):
...
@deco(d1=xx)
def work(w1):
...
def deco(work):
def _wrapper(work_arg):
return work(work_arg)
return _wrapper
@deco
def work_a(w1):
@deco
def work_b(w1, w2, w3=None):
1. 不知道使用你 deco 的 function 有多少個參數
def deco(work):
def _wrapper(*args, **kwargs):
return work(*args, **kwargs)
return _wrapper
@deco
def work_a(w1):
@deco
def work_b(w1, w2, w3=None):
就回傳可以吃任意個參數的 wrapper
def deco(work, d_arg1):
def _wrapper(*args, **kwargs):
print(d_arg1)
return work(*args, **kwargs)
return _wrapper
def work_a(w1, w2, w3=None):
...
work_a = deco(work_a, 5)
work_a(11, 22, 33)
2. 想讓 decorator 自身也接受參數
def deco(work, d_arg1):
def _wrapper(*args, **kwargs):
print(d_arg1)
return work(*args, **kwargs)
return _wrapper
def work_a(w1, w2, w3=None):
...
work_a = deco(work_a, 5)
work_a(11, 22, 33)
2. 想讓 decorator 自身也接受參數
可以,
但沒有 syntax sugar
@retry
def download(file):
......
@retry(attempts=5)
def download(file):
......
retry(download)
retry(attempts=5)(download)
藍色的部份,也就是 @ 後面的部份可以視作一個 expression,這個 expression 回傳的東西會被呼叫
def deco(d_arg1):
def _decorator(work):
def _wrapper(*args, **kwargs):
print(d_arg1)
return work(*args, **kwargs)
return _wrapper
return _decorator
def work_a(w1, w2): @deco(5)
... def work_a(w1, w2):
work_a = deco(5)(work_a) ...
work_a(11, 22)
讓 @xxx 獨立於 work 之外
def deco(work):
def _wrapper(*args, **kwargs):
return work(*args, **kwargs)
return _wrapper
deco(my_work)(11, 22)
def p_deco(d_arg1):
def _decorator(work):
def _wrapper(*args, **kwargs):
print(d_arg1)
return work(*args, **kwargs)
return _wrapper
return _decorator
p_deco(42)(my_work)(11, 22) (做了呼叫的) p_deco(42)
是一個吃 work 的 function --
亦即裡面定義的 _decorator
deco
是一個吃 work 的 function
def deco(work):
def _wrapper(*args, **kwargs):
return work(*args, **kwargs)
return _wrapper
@deco
def my_work(w1, w2):
def p_deco(d_arg1):
def _decorator(work):
def _wrapper(*args, **kwargs):
print(d_arg1)
return work(*args, **kwargs)
return _wrapper
return _decorator
@p_deco(42)
def my_work(w1, w2):
多了一層,因為和
“deco” 只是定義相比,
”p_deco(42)” 做了呼叫
Takeaway
my_func = some_decorator(my_func)
function 是一個「東西」
● 可以 assign
● 可以傳進另一個 function
● 可以定義在另一個 function,並回傳之
def retry(do_work):
def wrapper(work_arg):
for i in range(5):
try:
work_res = do_work(work_arg)
return work_res
except:
sleep(60)
return wrapper
retry(query_mysql) #work is not executed
res = retry(query_mysql)('select *')
decorator: syntax sugar
@measure_time
@cache
def work(w1):
......
def work(w1):
......
work = measure_time(
cache(
work))
r = work('123')
● 使用方式不變
● 擴充功能:
和黃金聖衣一樣
● 內在不變,但外在
變了
(你的work不是你的work)
def deco(work):
def _wrapper(*args, **kwargs):
return work(*args, **kwargs)
return _wrapper
@deco
def my_work(w1, w2):
def p_deco(d_arg1):
def _decorator(work):
def _wrapper(*args, **kwargs):
print(d_arg1)
return work(*args, **kwargs)
return _wrapper
return _decorator
@p_deco(42)
def my_work(w1, w2):
大家可以回家啦!
Reference
Reference
● https://www.python.org/dev/peps/pep-0318/ (must see)
● https://docs.python.org/3/reference/compound_stmts.html
#function
● Book “Guide to: learning Python Decorators”
● work 可以動,不代表你的 work 是你的 work
○ print(work.__name__)
○ https://hynek.me/articles/decorators/
○ http://blog.dscpl.com.au/2014/01/how-you-implemented-your-pyth
on.html
○ https://github.com/GrahamDumpleton/wrapt

More Related Content

PDF
Imugi: Compiler made with Python
PDF
Introduction to ad-3.4, an automatic differentiation library in Haskell
PDF
Advanced python
PDF
Functions in python
PDF
Being functional in PHP (DPC 2016)
PDF
Advanced Python, Part 2
PDF
Being functional in PHP (PHPDay Italy 2016)
PPTX
Python decorators
Imugi: Compiler made with Python
Introduction to ad-3.4, an automatic differentiation library in Haskell
Advanced python
Functions in python
Being functional in PHP (DPC 2016)
Advanced Python, Part 2
Being functional in PHP (PHPDay Italy 2016)
Python decorators

What's hot (20)

PPTX
Decorators Explained: A Powerful Tool That Should Be in Your Python Toolbelt.
PDF
Recursion to iteration automation.
PDF
Python profiling
ODP
Decorators in Python
PDF
Creating Lazy stream in CSharp
PDF
Docopt
KEY
(map Clojure everyday-tasks)
PDF
Коварный code type ITGM #9
PDF
C++ L05-Functions
PDF
Python Programming: Data Structure
PPTX
TCO in Python via bytecode manipulation.
PDF
C++ L04-Array+String
PDF
C++ L06-Pointers
PDF
C++ L03-Control Structure
PDF
CoffeeScript
PDF
ES6 - Next Generation Javascript
PDF
Python opcodes
PPTX
EcmaScript unchained
PDF
C++ L07-Struct
PDF
C++ L01-Variables
Decorators Explained: A Powerful Tool That Should Be in Your Python Toolbelt.
Recursion to iteration automation.
Python profiling
Decorators in Python
Creating Lazy stream in CSharp
Docopt
(map Clojure everyday-tasks)
Коварный code type ITGM #9
C++ L05-Functions
Python Programming: Data Structure
TCO in Python via bytecode manipulation.
C++ L04-Array+String
C++ L06-Pointers
C++ L03-Control Structure
CoffeeScript
ES6 - Next Generation Javascript
Python opcodes
EcmaScript unchained
C++ L07-Struct
C++ L01-Variables
Ad

Similar to Python decorators (中文) (20)

PPTX
DevOps with Fabric
KEY
DjangoCon US 2011 - Monkeying around at New Relic
KEY
Djangocon11: Monkeying around at New Relic
PPTX
JNTUK python programming python unit 3.pptx
PDF
Functional Programming with Groovy
PDF
Python idiomatico
PDF
Pydiomatic
PPTX
Chapter 02 functions -class xii
PPTX
2 Functions2.pptx
PDF
Funkcija, objekt, python
PDF
Fantastic DSL in Python
PPT
User defined functions
PDF
Currying and Partial Function Application (PFA)
KEY
Testing My Patience
PDF
Python magicmethods
PDF
Introduction to Functional Programming with Scala
PPTX
LinkedIn TBC JavaScript 100: Functions
PDF
Attributes Unwrapped: Lessons under the surface of active record
DevOps with Fabric
DjangoCon US 2011 - Monkeying around at New Relic
Djangocon11: Monkeying around at New Relic
JNTUK python programming python unit 3.pptx
Functional Programming with Groovy
Python idiomatico
Pydiomatic
Chapter 02 functions -class xii
2 Functions2.pptx
Funkcija, objekt, python
Fantastic DSL in Python
User defined functions
Currying and Partial Function Application (PFA)
Testing My Patience
Python magicmethods
Introduction to Functional Programming with Scala
LinkedIn TBC JavaScript 100: Functions
Attributes Unwrapped: Lessons under the surface of active record
Ad

Recently uploaded (20)

PPTX
Computer Software and OS of computer science of grade 11.pptx
PPTX
Why Generative AI is the Future of Content, Code & Creativity?
PDF
Types of Token_ From Utility to Security.pdf
PDF
DuckDuckGo Private Browser Premium APK for Android Crack Latest 2025
PDF
MCP Security Tutorial - Beginner to Advanced
PPTX
Tech Workshop Escape Room Tech Workshop
PDF
Wondershare Recoverit Full Crack New Version (Latest 2025)
PDF
DNT Brochure 2025 – ISV Solutions @ D365
PDF
Salesforce Agentforce AI Implementation.pdf
PPTX
Advanced SystemCare Ultimate Crack + Portable (2025)
PDF
Multiverse AI Review 2025: Access All TOP AI Model-Versions!
PDF
Top 10 Software Development Trends to Watch in 2025 🚀.pdf
PDF
Time Tracking Features That Teams and Organizations Actually Need
PPTX
Introduction to Windows Operating System
PDF
Designing Intelligence for the Shop Floor.pdf
PDF
AI/ML Infra Meetup | LLM Agents and Implementation Challenges
PPTX
"Secure File Sharing Solutions on AWS".pptx
PPTX
assetexplorer- product-overview - presentation
PPTX
CNN LeNet5 Architecture: Neural Networks
PDF
How Tridens DevSecOps Ensures Compliance, Security, and Agility
Computer Software and OS of computer science of grade 11.pptx
Why Generative AI is the Future of Content, Code & Creativity?
Types of Token_ From Utility to Security.pdf
DuckDuckGo Private Browser Premium APK for Android Crack Latest 2025
MCP Security Tutorial - Beginner to Advanced
Tech Workshop Escape Room Tech Workshop
Wondershare Recoverit Full Crack New Version (Latest 2025)
DNT Brochure 2025 – ISV Solutions @ D365
Salesforce Agentforce AI Implementation.pdf
Advanced SystemCare Ultimate Crack + Portable (2025)
Multiverse AI Review 2025: Access All TOP AI Model-Versions!
Top 10 Software Development Trends to Watch in 2025 🚀.pdf
Time Tracking Features That Teams and Organizations Actually Need
Introduction to Windows Operating System
Designing Intelligence for the Shop Floor.pdf
AI/ML Infra Meetup | LLM Agents and Implementation Challenges
"Secure File Sharing Solutions on AWS".pptx
assetexplorer- product-overview - presentation
CNN LeNet5 Architecture: Neural Networks
How Tridens DevSecOps Ensures Compliance, Security, and Agility

Python decorators (中文)