装饰器:以某种方式增强函数。
两大特性:1、可以将被装饰的函数替换成其他函数。
2、在加载模块时立即执行。

案例1
def make_avarage():
count=0
total=0
def averager(new_value):
count+=1
total+=new_value
return total/count
return averager
这里会报错,averager里面是一个新的 count、total变量

案例2
使用nolocal作用:将变量标记为自由变量,
def make_avarage():
count=0
total=0
def averager(new_value):
nonlocal count,total
count+=1
total+=new_value
return total/count
return averager

案例3
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Sun May 3 23:27:22 2020 @author: root
""" promos=[]
def promotion(promo_func):
promo.append(promo_func)
return promo_func @promotion
def FidelityPromo(order):
return order.total()*0.05 if order.customer.fidelity>=1000 else 0 @promotion
def BulkItemPromo(order):
discount = 0
for item in order.cart:
if item.quantity>=20:
discount+=item.total()*0.1
return discount @promotion
def LargeOrderPromo(order):
discount_items = {item.product for item in order.cart}
if len(discount_items)>=10:
return order.total()*0.07
return 0 def best_promo(order):
return max(promo(order) for promo in promos)

二、@property:方法伪装属性,方法返回值及属性值,被装饰方法不能有参数,必须实例化后调用,类不能调用
#@ property
#将一个方法伪装成属性,被修饰的特性方法,内部可以实现处理逻辑,但对外提供统一的调用方式,实现一个实例属性的

getter
setter
d elete
三种方法的内部逻辑,具体含义看示
class Data:

    def __init__(self):
self.number = 123 @property
def operation(self):
return self.number

@operation.getter
def operation(self):
return self.number @operation.setter
def operation(self, number):
self.number = number @operation.deleter
def operation(self):
del self.number

案例1----普通写法
class Student(object):
def get_score(self):
return self._score

def set_score(self,value):
if not isinstance(value,int):
raise ValueError('pppppp')
if value < 0 or value > 100:
raise ValueError('score must between 0 ~ 100!')
self._score = value

Python内置的@property装饰器就是负责把一个方法变成属性调用
案例1----装饰器写法


class Student(object):

    @property
    def score(self):
        return self._score

    @score.setter
    def score(self, value):
        if not isinstance(value, int):
            raise ValueError('pppppp')
        if value < 0 or value > 100:
            raise ValueError('score must between 0 ~ 100!')
        self._score = value
s=Student()
s.score=60
s.score=9999
print (s.score)

三、类装饰器:类装饰器使用地方较少,核心是通过复写类的回调方法call.

装饰器应用场景:

1、引入日志
2、函数执行时间统计
3、执行函数前预备处理
执行函数后清理功能
权限校验等场景
缓存

方法:__call__
__call__ 方法,不得不先提到一个概念,就是可调用对象(callable),我们平时自定义的函数、内置函数和类都属于可调用对象,但凡是可以把一对括号()应用到某个对象身上都可称之为可调用对象,判断对象是否为可调用对象可以用函数 callable
class Add:

def __init__(self, fn):
print("初始化")
self.num = 44
self.fn = fn

def __call__(self, *args, **kwargs):
print("类装饰器开始工作")
return self.fn(self.num)

@Add
def test(n):
return 4+n

if __name__ == '__main__':
num = test()
print(num)

结果:
初始化
<function test at 0x7f95f883bc20>
类装饰器开始工作
44
48
 
 

案例1

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Mon May 4 22:11:44 2020 @author: root
简单注册表
""" funcs = []
def register(func):
funcs.append(func)
return func @register
def a():
return 3 @register
def b():
return 5 def c():
return 8 # 访问结果
result = [func() for func in funcs]
print(funcs)
print(result) # [<function a at 0x7f95f8837050>, <function b at 0x7f95f8837290>]
# [3, 5]

案例2

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Mon May  4 22:14:37 2020

@author: root

注册表隔离(使用类的不同实例)
"""

class Registry(object):
    def __init__(self):
        self._funcs=[]

    def register(self,func):
        self._funcs.append(func)

    def run_all(self):
        return [func() for func in self._funcs]

r1=Registry()
r2=Registry()

@r1.register
def a():
    return 3

@r2.register
def b():
    return 5

案例3

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Mon May 4 22:30:41 2020 @author: root 用户验证
""" from functools import wraps class User(object):
def __init__(self, username, email):
self.username = username
self.email = email class AnonymousUser(object):
def __init__(self):
self.username = self.email = None def __nonzero__(self): # 将对象转换为bool类型时调用
return False def requires_user(func):
@wraps(func)
def inner(user, *args, **kwargs): # 由于第一个参数无法支持self, 该装饰器不支持装饰类
if user and isinstance(user, User):
return func(user, *args, **kwargs)
else:
raise ValueError("非合法用户")
return inner a=User('teddy', '120@163.com')
print (a)

案例3

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Mon May 4 22:36:47 2020 @author: root 异常捕获
""" import json
from functools import wraps class Error1(Exception):
def __init__(self, msg):
self.msg = msg
def __str__(self):
return self.msg def json_output(func):
@wraps(func)
def inner(*args, **kwargs):
try:
result = func(*args, **kwargs)
except Error1 as ex:
result = {"status": "error", "msg": str(ex)}
return json.dumps(result)
return inner # 使用方法
@json_output
def error():
raise Error1("该条异常会被捕获并按JSON格式输出")

案例3

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Mon May 4 22:40:47 2020 @author: root 日志管理
"" import time
import logging
from functools import wraps def logged(func):
@wraps(func)
def inner(*args, **kwargs): # *args可以装饰函数也可以装饰类
start = time.time()
result = func(*args, **kwargs)
exec_time = time.time() - start
logger = logging.getLoger("func.logged")
logger.warning("{} 调用时间:{:.2} 执行时间:{:.2}s 结果:{}".format(func.__name__, start, exec_time, result))
资源清理#import pymysql

class DBConnection(object):
def __init__(self, *args, **kwargs):
self.args,self.kwargs = args, kwargs def __enter__(self):
self.conn = pymysql.connect(*args, **kwargs)
return self.conn.cursor() def __exit__(self, exc_type, exc_instance, trackback):
self.conn.close()
 案例来源:https://www.cnblogs.com/superhin/p/11454823.html

流畅的python--装饰器的更多相关文章

  1. Python装饰器:套层壳我变得更强了

    Python装饰器:套层壳我变得更强了 Python装饰器:套层壳我变得更强了 关于作用域和闭包可以聊点什么? 什么是作用域 什么是闭包 装饰器:套层壳我变得更强了 参考资料 昨天阅读了<Pyt ...

  2. 关于python装饰器

    关于python装饰器,不是系统的介绍,只是说一下某些问题 1 首先了解变量作用于非常重要 2 其次要了解闭包 def logger(func): def inner(*args, **kwargs) ...

  3. python装饰器通俗易懂的解释!

    1.python装饰器 刚刚接触python的装饰器,简直懵逼了,直接不懂什么意思啊有木有,自己都忘了走了多少遍Debug,查了多少遍资料,猜有点点开始明白了.总结了一下解释得比较好的,通俗易懂的来说 ...

  4. Python 装饰器学习

    Python装饰器学习(九步入门)   这是在Python学习小组上介绍的内容,现学现卖.多练习是好的学习方式. 第一步:最简单的函数,准备附加额外功能 1 2 3 4 5 6 7 8 # -*- c ...

  5. python 装饰器修改调整函数参数

    简单记录一下利用python装饰器来调整函数的方法.现在有个需求:参数line范围为1-16,要求把9-16的范围转化为1-8,即9对应1,10对应2,...,16对应8. 下面是例子: def fo ...

  6. python 装饰器学习(decorator)

    最近看到有个装饰器的例子,没看懂, #!/usr/bin/python class decorator(object): def __init__(self,f): print "initi ...

  7. Python装饰器详解

    python中的装饰器是一个用得非常多的东西,我们可以把一些特定的方法.通用的方法写成一个个装饰器,这就为调用这些方法提供一个非常大的便利,如此提高我们代码的可读性以及简洁性,以及可扩展性. 在学习p ...

  8. 关于python装饰器(Decorators)最底层理解的一句话

    一个decorator只是一个带有一个函数作为参数并返回一个替换函数的闭包. http://www.xxx.com/html/2016/pythonhexinbiancheng_0718/1044.h ...

  9. Python装饰器由浅入深

    装饰器的功能在很多语言中都有,名字也不尽相同,其实它体现的是一种设计模式,强调的是开放封闭原则,更多的用于后期功能升级而不是编写新的代码.装饰器不光能装饰函数,也能装饰其他的对象,比如类,但通常,我们 ...

  10. Python装饰器与面向切面编程

    今天来讨论一下装饰器.装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志.性能测试.事务处理等.装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量函数中与函数 ...

随机推荐

  1. centos 7 能ping通但是telnet 22 不通解决方法

    试过关闭Linux防火墙,打开sshd服务,修改ens33为enth0.发现不好使. 经过不断的努力我发现,windows系统里面的VMware Network Adapter VMnet8设置的ip ...

  2. 【模拟7.27】题(liu_runda的神题)(卡特兰数,组合数)

    考场的SB经验不再分享 case 0: 一道组合计数的水题,具体不再讲可以看以前的相似题 case 1: 很明显的卡特兰计数,我们把长度为n的序列看成01串 关于卡特兰计数的详细的讲解 由此可知我们需 ...

  3. JAVA并行程序基础二

    JAVA并行程序基础二 线程组 当一个系统中,如果线程较多并且功能分配比较明确,可以将相同功能的线程放入同一个线程组里. activeCount()可获得活动线程的总数,由于线程是动态的只能获取一个估 ...

  4. 在vue项目中使用echarts

    1.安装echarts依赖npm install echarts --save 2.在要使用的页面引入import echarts from 'echarts'v5之后使用 import * echa ...

  5. 中文NER的那些事儿3. SoftLexicon等词汇增强详解&代码实现

    前两章我们分别介绍了NER的基线模型Bert-Bilstm-crf, 以及多任务和对抗学习在解决词边界和跨领域迁移的解决方案.这一章我们就词汇增强这个中文NER的核心问题之一来看看都有哪些解决方案.以 ...

  6. 11、linux的目录结构

    11.1.查看磁盘的id: blkid 11.2.linux目录类似一个倒挂的树: / 是所有目录的顶点,目录磁盘和分区是没有关联的,因此/下不同的目录会对应不同的磁盘的不同的分区: linux中硬盘 ...

  7. 4、oracle表操作

    4.1.dml操作: 1.查看当前用户下所有的表: select * from user_tables; 2.查看某表的大小: select sum(bytes)/(1024*1024) as &qu ...

  8. jquery 选择器 模糊匹配

    根据name值匹配 1.查询前缀为aa的数据 $("div[name^='aa']"); 2.查询后缀为aa的所有div的jquery对象 $("div[name$='a ...

  9. POJ 1220 大数字的进制转换,偷下懒,用java

    题意为进制转换,Java的大数类就像是作弊 import java.math.BigInteger; import java.util.Scanner; public class Main { pub ...

  10. 面试题五:Spring

    Spring IoC 什么是IoC? 容器创建Bean对象,将他们装配在一起,配置并且管理它们的完整生命周期. Spring容器使用依赖注入来管理组成应用程序的Bean对象: 容器通过提供的配置元数据 ...