之前三篇
001-函数技巧\变量\包\标准库
002-高阶函数技巧-lambda\filter\map\reduce 函数
003–文件の读写
004–面向对象
装饰器
- 用于拓展原来函数的一种功能函数
- 返回函数的函数
- 在不用更改原函数代码前提下,给函数增加新功能
- 想打印
hello
函数,可以加一个hello_wrapper
函数来打hello
def hello():
""" 简单功能模拟 """
print('hello world')
def test():
print('test ..')
def hello_wrapper():
""" 新的函数,包裹原来的hello """
print('进入函数hello')
hello()
print('结束执行hello')
def test_wrapper():
print('进入函数hello')
test()
print('结束执行hello')
if __name__ == '__main__':
# hello()
hello_wrapper()
# 进入函数hello
# hello world
# 结束执行hello
- 但如果每次需要打印不同的函数名,那需要写很多类似hello_wrapper的函数,如上述代码的
test函数
,才行,因此引入装饰器.
装饰器代码如下:
def log(func):
""" 记录函数执行的日志 """
def wrapper():
print('start...')
func()
print('end..')
return wrapper
def log2(func):
""" 记录函数执行的日志 """
def wrapper():
print('SSTART...')
func()
print('EEEND..')
return wrapper
def log_in(func):
""" 记录函数执行的日志 """
def wrapper():
print('开始进入...')
func()
print('结束..')
return wrapper
@log2
def hello():
""" 简单功能模拟 """
print('hello world')
@log
@log_in
def test():
print('test ..')
if __name__ == '__main__':
hello()
test()
"""输出结果:
SSTART...
hello world
EEEND..
start...
开始进入...
test ..
结束..
end..
"""
带参数的装饰器
通过下边代码,学习带参数的装饰器
# 装饰器
def log(name=None):
def decorator(func):
def warrper():
print('{0}.start...'.format(name))
func()
print('{0}.end...'.format(name))
return warrper
return decorator
@log()
def hello():
"""功能模拟"""
print('世界真精彩')
hello()
"""输出:
None.start...
世界真精彩
None.end...
"""
# 若:-------------------------
@log('you')
def hello():
"""功能模拟"""
print('世界真精彩')
hello()
"""输出:
you.start...
世界真精彩
you.end...
"""
如果想传入带计算的参数怎么办?
- 举例如下
# 带参数装饰器
def log(name=None):
""" 记录函数执行的日志 """
def decorator(func):
def wrapper(*args, **kwargs):
print('{0}.start...'.format(name))
print(args)
print(kwargs)
rest = func(*args, **kwargs)
print('{0}.end..'.format(name))
return rest
return wrapper
return decorator
@log('from add')
def add(a, b, *args, **kwargs):
print('--------')
return a + b
if __name__ == '__main__':
rest = add(5, 6, k=5, v=6)
print(rest)
# 输出内容
'''
from add.start...
(5, 6)
{'k': 5, 'v': 6}
--------
from add.end..
11
'''
- 扩展练习理解一下:
# 装饰器练习一道
def wrapper(func):
def inner(age):
# 增加功能判断
if age<0:
age=0
# 调用原函数
func(age)
return inner
@wrapper
def getAge(age):
print(f'今年{age}岁')
getAge(-1)
getAge(-11)
getAge(10)
getAge(110)
"""输出结果如下:
今年0岁
今年0岁
今年10岁
今年110岁
"""
装饰器属性承接原函数属性
- 使用@wraps(func)函数调用原函数属性,如案例中文档及注释
from functools import wraps
def log(name=None):
""" 记录函数执行的日志 """
def decorator(func):
@wraps(func)
def wrapper2(*args, **kwargs):
""" 装饰器内部的函数 """
print('{0}.start...'.format(name))
print('-----warpper: {0}'.format(func.__name__))
print('-----warpper: {0}'.format(func.__doc__))
rest = func(*args, **kwargs)
print('{0}.end..'.format(name))
return rest
# wrapper2.__doc__ = func.__doc__
# wrapper2.__name__ = func.__name__
return wrapper2
return decorator
@log('hello')
def hello():
""" 简单功能模拟 """
print('hello world')
if __name__ == '__main__':
print('doc: {0}'.format(hello.__doc__))
print('name: {0}'.format(hello.__name__))
print('--------------')
hello()
"""输出如下
doc: 简单功能模拟
name: hello
--------------
hello.start...
-----warpper: hello
-----warpper: 简单功能模拟
hello world
hello.end..
"""
类的装饰器
装饰器给类新增加类功能函数,如下边,给Cat增加了.eat功能
def eat(cls):
""" 吃东西装饰器 """
cls.eat = lambda self: print('{0}>>>我要吃东西'.format(self.name))
return cls
@eat
class Cat(object):
""" 猫类 """
def __init__(self, name):
self.name = name
if __name__ == '__main__':
cat = Cat('小黑')
cat.eat()
"""小黑>>>我要吃东西"""
引用函数的装饰器
def f(self):
print('{0}>我要吃东西'.format(self.name))
print('0000000000增加的')
def eat(cls):
""" 吃东西装饰器 """
cls.eat = f
return cls
@eat
class Cat(object):
""" 猫类 """
def __init__(self, name):
self.name = name
if __name__ == '__main__':
cat = Cat('小黑')
cat.eat()
"""
小黑>我要吃东西
0000000000增加的
"""