python进阶
2. 从函数-闭包到装饰器
2.1 函数进阶
2.1.1 函数中定义函数
def functionOne():
def inner():
print("this is inner")
print("this is outer")
内部函数不会自动执行,因为 内部函数根本没有打印,
2.1.2 函数中返回函数
def functionTwo():
def innerTwo():
print("this is inner")
return innerTwo
def test_function():
functionTwo()()
2.1.3 函数中传入函数
def functionThree(func):
func()
functionThree(functionOne)
当我们传入参数和返回参数的时候,传入和返回,我们都可以理解为函数名,不需要带括号,我们可以从C语言的角度将 其理解为内存地址,当调用的时候,直接带() 进行直接调用。
2.2 装饰器
2.2.1 如何定义装饰器
先来说一说什么是装饰器:
python中的装饰器就是在不改变原代码的情况下,对原有函数的功能进行扩展
2.3装饰器分类
-
函数装饰器----用函数写的装饰器
- 装饰器装饰函数
- 装饰器装饰类
-
类装饰器------用类写的装饰器
- 装饰器装饰函数
- 装饰器装饰类
2.4 函数装饰器-----装饰函数
从嵌套函数一步一步开始
2.4.1 嵌套函数
def big():
def small():
print("======之前输出========")
f = big()
print("======之后输出========")
return f
return small
big()()
2.4.2 最简单的函数装饰器
#一个不传参的函数装饰器
def out(func):
def inner():
print("======之前输出========")
f= func()
print("======之后输出========")
return f
return inner
def task():
return 3
out(task)()
@out # out= out(note) 他是inner类型,所以我们会发现,当我们打印 print(note)的时候
def note():
return "sss"
print(note)
我们会发现,装饰器其实就是我们 python 自己 进行的函数调用 只不过使用@符号进行简写
2.4.3 函数有参数
def record(func):
def link(*args, **kwargs):
print(*args)
f = func(*args,**kwargs)
print(*kwargs)
return f
return link
@record
def name(a,b):
return 2
name(2,4)
2.4.4 解释器传参
#带参数的函数装饰器
def count_time_args(mas=None):
def record(func):
def link(*args, **kwargs):
print(*args)
f = func(*args, **kwargs)
print(*kwargs)
print("=======当前调用者:========",mas)
return f
return link
return record
@count_time_args(mas="baidu")
def test_name(a,b,c):
print(a,b,c)
test_name(3,4,5)
2.5 函数装饰器---装饰类
2.5.1 装饰器不传参
# =====上面全部都是函数装饰器修饰函数,当函数装饰器修饰类时,上面以第一个传入的就不是函数,而是一个类
def record(cls):
def link(*args, **kwargs):
print(*args,"======")
f = cls(*args, **kwargs)
print(*kwargs,"======")
print("=======当前调用者:========")
return f
return link
@record
class Tag():
def __init__(self):
self.name = "lisi"
print(self.name)
tag = Tag()
2.5.2 传参
def count_time_arg(mas=None):
def record(cls): #传递的类对象
def link(*args, **kwargs): #传递init的参数
print(*args)
f = cls(*args, **kwargs)
print(*kwargs)
print("=======当前调用者:========",mas)
return f
return link
return record
#如果装饰器需要带参数,我们必须要写括号,不然会报错
@count_time_arg()
class pig():
def __init__(self):
self.name = "lisi"
print(self.name)
pig()
我们会发现:两种是一样的,cls和func只不过是一个参数名是没有影响的,参数名可以随便起
2.6 类装饰器
#类装饰器
from datetime import datetime
class Mark:
def __init__(self, func): #传入的是函数对象或者类对象
self.func = func
print("=====执行init方法=====")
def __call__(self, *args, **kwargs):
print("======执行call前======")
f =self.func(*args,**kwargs)
print("====执行call方法====")
return f
@Mark
def test():
print("this is a test")
test()
#类装饰器有参数的时候,init方法传入的参数
class MarkTag():
def __init__(self, time = datetime.now()):
print("this time is {now}".format(now=time))
def __call__(self, func):
def wrapper(*args, **kwargs):
print("==========执行前=======")
res = func(*args,**kwargs)
print("========执行后=========")
return res
return wrapper
@MarkTag(333)
def getName():
print("this is jack")
getName()
#=====当修饰的是类的是类的时候
其实跟我们的函数只是写法不太一样而已,可以自己手动写一写。