Python闭包和装饰器(包括有无参数的函数装饰器和类装饰器)
·
一、闭包
1、什么是闭包
a、必须有内嵌函数
b、内部函数引用外部函数的变量
c、外部函数的返回值是内部函数
# 内部函数inner()在这就是一个闭包函数
# outer函数嵌套inner函数
# inner函数使用变量a和b
# outer函数的返回值是inner
def outer(a):
b = 10
def inner():
#参数a和变量b都成inner函数的私有变量
print(a+b)
return inner
f = outer(5) # f相当于inner
a = 7
f() # f()相当于inner()
# 输出的结果是15
2、闭包的作用:
保存外部函数的变量,不会随着外部函数调用完而销毁
上面的例子变量a和b不会随着outer函数的调用完而销毁,所以后面即使将a赋值为7,输出的结果还是15
二、装饰器
装饰器的本质是闭包,在不改变函数或类的源代码基础上,添加额外功能
给函数使用两个装饰器,执行顺序是由里向外执行
1、函数装饰器
1.1、不带参数的装饰器
a、给函数增加计时功能的装饰器
import time
def runtime(func):
def inner():
start = time.time()
func()
end = time.time()
print(f"函数执行用时{end - start}s")
return inner
@runtime
# @runtime 相当于set_time= runtime(set_time)
def set_time():
time.sleep(10)
set_time()
# 输出:函数执行用时10.012602090835571s
b、给函数增加日志功能
def log(func):
def inner():
print(f"函数是{func.__name__}")
return inner
@log
def add():
a = 6
b = 99
return a+b
add()
#输出:函数是add
1.2、带参数的装饰器
import time
def user(name):
def log(func):
def inner():
start = time.time()
func()
end = time.time()
print(f"{name}使用函数{func.__name__}执行用时{end - start}s")
return inner
return log
@user(name="张三")
def func():
a = 6
b = 99
return a + b
func()
# 输出:张三使用函数func执行用时0.0s
2、类装饰器
Python还提供了类装饰器与@staticmethod,@classmethod,@property面向对象编程中常用的装饰器
• staticmethod:把类中定义的实例方法变成静态方法
• classmethod:把类中定义的实例方法变成类方法
• property:把类中定义的实例方法变成类属性。
2.1、写一个计时功能的类装饰器
1、不带参数
import time
class Runtime:
def __init__(self, func):
self.func = func
def __call__(self, *args, **kwargs):
start = time.time()
self.func()
end = time.time()
print(f"函数执行用时{end - start}s")
@Runtime
def f():
time.sleep(5)
f()
# 输出:函数执行用时5.004265785217285s
2、带参数
import time
class Runtime:
def __init__(self, func):
self.func = func
def __call__(self,t, *args, **kwargs):
start = time.time()
self.func(t)
end = time.time()
print(f"函数执行用时{end - start}s")
@Runtime
def f(t):
time.sleep(t)
f(6)
#输出:函数执行用时6.008318901062012s
2.2@property应用
@property最大的好处就是在类中把一个方法变成属性调用,起到既能检查属性,还能用属性的方式来访问该属性的作用。可定义只读属性就是写保护,也就是真正意义上实现私有属性(属性前双下划线)可以访问的。
class Person(object):
def __init__(self, name):
self.name = name
self.__age = 15
@property
def age(self):
return self.__age
zs = Person('zhangsan')
print(zs.age) # 结果为15
zs.age = 18 # 报错无法给年龄赋值
因为@property将age函数变成age属性,间接访问__age__,并且对age有写保护,所以zs.age赋值时报错。
更多推荐
已为社区贡献1条内容
所有评论(0)