Python闭包和装饰器
跳转到导航
跳转到搜索
要先理解闭包,再理解装饰器
闭包
什么是闭包
#定义一个函数
def test(number):
#在函数内部再定义一个函数,并且这个函数用到了外边函数的变量,那么将这个函数以及用到的一些变量称之为闭包
def test_in(number_in):
print("in test_in 函数, number_in is %d"%number_in)
return number+number_in
#其实这里返回的就是闭包的结果
return test_in
#给test函数赋值,这个20就是给参数number
这时候 ret 指向是test_in 也就是里面的那个function
ret = test(20)
#注意这里的100其实给参数number_in
print(ret(100))
#注意这里的200其实给参数number_in
print(ret(200))
运行结果:
in test_in 函数, number_in is 100
120
in test_in 函数, number_in is 200
220
cat 1.py
"""
--1--
--3--
*************************
--2--
200
"""
def test(number):
print("--1--")
def test_in():
print("--2--")
print(number+100)
print("--3--")
return test_in
ret = test(100)
print("*"*25)
ret()
def test(number):
print("--1--")
def test_in():
print("--2--")
print(number+100)
print("--3--")
return test_in
test(100)
#ret = test(100)
"""
--1--
--3--
"""
def test(number):
print("--1--")
def test_in(number2):
print("--2--")
print(number+number2)
print("--3--")
return test_in
ret = test(100)
print("-"*30)
ret(1)
ret(100)
ret(200)
"""
python3 01-闭包/01-闭包1.py
--1--
--3--
------------------------------
--2--
101
--2--
200
--2--
300
"""
装饰器
现在,假设我们要增强now()函数的功能,比如,在函数调用前后自动打印日志,但又不希望修改now()函数的定义,这种在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator)。
本质上,decorator就是一个返回函数的高阶函数。所以,我们要定义一个能打印日志的decorator,可以定义如下:
把@log放到now()函数的定义处,相当于执行了语句:
now = log(now)
"""
---正在验证权限----
---f1---
"""
def w1(func):
def inner():
print("---正在验证权限----")
func()
return inner
def f1():
print("---f1---")
def f2():
print("---f2---")
#innerFunc = w1(f1)
#innerFunc()
#这是的f1 其实是inner了 只有func才是原来的f1
f1 = w1(f1)
f1()
运行流程如下 一开始是 f1 = w1(f1) 先算右边的 w1(f1) 这时候 func指向def f1 ,而左边的f1 为def inner 所以 运行最后一行 f1()时 就是先运行 inner fun 打印 ---正在验证权限----,第二步 func() 也就是原来的f1 fun 所以打印---f1---
不明请看下面的wrapp原理图片
<2019-03-28 四>
****************************分隔线**********************************************************
#定义函数:完成包裹数据
"""
----1---
----2---
----3---
<b><i>hello world-3</i></b>
"""
def makeBold(fn):
def wrapped():
print("----1---")
return "<b>" + fn() + "</b>"
return wrapped
#定义函数:完成包裹数据
def makeItalic(fn):
def wrapped():
print("----2---")
return "<i>" + fn() + "</i>"
return wrapped
@makeBold
@makeItalic
def test3():
print("----3---")
return "hello world-3"
ret = test3()
print(ret)
decorator2024
FUNCTION DECORATORS
Python decorators are a special syntax for functions which take other functions as arguments. Python
functions are objects, so any function can take a function as an argument. The decorator syntax provides a
clean and easy way to do this. The basic format of a decorator is:
In [2]: def some_decorator(wrapped_function):
def wrapper():
print('Do something before calling wrapped function')
wrapped_function()
print('Do something after calling wrapped function')
return wrapper
You can define a function and pass it as an argument to this function:
In [3]: def foobat():
...:
print('foobat')
...:
In [4]: f = some_decorator(foobat)
In [5]: f()
Do something before calling wrapped function
foobat
Do something after calling wrapped function
The decorator syntax simplifies this by indicating which function should be wrapped by decorating it with
@decorator_name. Here is an example using the decorator syntax with our some_decorator function:
In [6]: @some_decorator
...: def batfoo():
...:
print('batfoo')
...:
In [7]: batfoo()
Do something before calling wrapped function
batfoo
Do something after calling wrapped function
Now you call your wrapped function using its name rather than the decorator name. Pre-built functions
intended as decorators are offered both as part of the Python Standard Library (staticMethod,
classMethod) and as part of third-party packages, such as Flask and Click.
decorator2025
入门 Python 装饰器最重要的是搞懂两个核心概念:
函数是对象,可以作为参数传递
装饰器其实就是一个“返回函数的函数”
第一步:理解函数是“变量”
def greet():
print("Hello!")
a = greet # 把函数赋值给变量
a() # 调用函数 -> 输出 Hello!
二步:函数作为参数传递
def run(func):
func()
def hello():
print("Hi!")
run(hello) # 输出 Hi!
第三步:返回函数的函数(闭包)
def outer():
def inner():
print("I am inner!")
return inner
f = outer()
f() # 输出 I am inner!
第四步:最简单的装饰器
def decorator(func):
def wrapper():
print("Before")
func()
print("After")
return wrapper
@decorator
def say_hello():
print("Hello!")
say_hello()
输出:
Before
Hello!
After
总结记忆口诀:
装饰器 = “外函数包住原函数” + @语法糖
✅ 学习建议: 阶段 学什么 推荐练习 新手 会写不带参数的装饰器 打印前后、计时器装饰器 熟悉函数式编程 理解闭包、*args 和 **kwargs 写带参数的装饰器 熟悉标准库 掌握 functools.wraps, lru_cache 给函数加缓存、限制调用次数等 实战 学 Flask/FastAPI/Django 中的装饰器 权限验证、API 日志、限流装饰器等
需要我为你定制一个「装饰器 7 天入门计划」或提供练习题
@decorator 的作用
@decorator
def say_hello():
print("Hello")
等价于:
def say_hello():
print("Hello")
say_hello = decorator(say_hello)
参考
https://segmentfault.com/a/1190000004461404
http://www.cnblogs.com/ChrisChen3121/p/3208119.html