接收被装饰的函数作为参数,不修改原函数,实现额外的功能;
在很多场景下都可以用到装饰器,比如web应用中服务器返回结果前判断用户登录状态;完成操作后的日志打印等。
2、闭包定义:外函数中定义1个内函数;内函数必须使用外函数的变量;外函数返回值是内函数
和装饰器的区别:闭包外函数接收的是变量;装饰器接收的是函数(即装饰器是传递函数的闭包)
简单的闭包示例如下:
def outer(i):
def inner(j):
print("i: ", i)
print("j: ", j)
return i + j
return inner
f = outer(3)
print(f(2))
# 运行结果:
'''
i: 3
j: 2
5
'''
3、装饰器
装饰器的一般格式如下:
装饰器定义:
def 函数装饰器名称(func): def 内嵌函数(*args, **kwargs) 需要添加的新功能 return func(*args, **kwargs) return 内嵌函数
装饰器使用:
@函数装饰器名称 def 被装饰的函数(参数): 函数体3.1、不带参数的装饰器
简单示例如下:
import time
def outer(func):
def inner():
start = time.time()
func()
count = time.time() - start
print("程序执行时间:{}".format(count))
return inner
@outer
def func1():
time.sleep(3)
print("this is a test func.")
func1()
# 运行结果:
'''
this is a test func.
程序执行时间:3.0140182971954346
'''
# 说明:原函数功能为打印一个字符串,在不改变原函数代码的前提下,装饰器为原函数新增了统计程序执行时间的功能。
3.2、原函数传参
简单示例如下:
import time
def outer(func):
def inner(*args, **kwargs):
start = time.time()
print(args, type(args))
print(kwargs, type(kwargs))
func(*args, **kwargs)
count = time.time() - start
print("程序执行时间:{}".format(count))
return inner
@outer
def func1(p1, p2, p3):
time.sleep(3)
print("this is a test func.")
func1(1, 2, p3=3)
# 运行结果:
'''
(1, 2)
{'p3': 3}
this is a test func.
程序执行时间:3.01261830329895
'''
# 说明:原函数作为参数传递给外函数,原函数的参数传递给内函数。
3.3、装饰器函数传参
示例如下:
def outer1(param):
def outer(func):
def inner(*args, **kwargs):
start = time.time()
print(args, type(args))
print(kwargs, type(kwargs))
print(param)
func(*args, **kwargs)
count = time.time() - start
print("程序执行时间:{}".format(count))
return inner
return outer
@outer1(100)
def func1(p1, p2, p3):
time.sleep(3)
print("this is a test func.")
func1(1, 2, p3=3)
# 运行结果:
'''
(1, 2)
{'p3': 3}
100
this is a test func.
程序执行时间:3.010993719100952
'''
# 说明:最外层函数接收装饰器函数传递的参数,中间层接收被装饰的函数,内层函数接收被装饰函数的参数
4、python内置装饰器
4.1、@property
把实例方法变为同名属性
4.2、@staticmethod改变方法为静态方法,无需隐性的第一参数,可通过类/实例调用
4.3、@classmethod改变方法为类方法,第一个参数cls表示自身类,隐式的将类做为对象,传递给方法。可通过类/实例调用
示例如下:
class Circle:
def __init__(self, r=0):
self.r = r
@property
def area(self):
return 3.14 * self.r * self.r
def double_area(self):
return self.area * 2
@staticmethod
def length(r):
return 2 * 3.14 * r
@classmethod
def color(cls, col):
print("the circle color is %s" % col)
c = Circle(1)
print(c.area, c.double_area()) # 调用时不可以写成area()
print(c.length(5)) # staticmethod可通过实例调用
print(Circle.length(5)) # staticmethod可通过类直接调用
c.color("red") # classmethod可通过实例调用
Circle.color("red") # classmethod可通过类直接调用
# 运行结果:
'''
3.14 6.28
31.400000000000002
31.400000000000002
the circle color is red
the circle color is red
'''



