Python装饰器

原文链接:https://www.zhihu.com/question/26930016/answer/1047233982

 

1、定义:装饰器,顾名思义,就是增强函数或类的功能的一个函数。

举例:现计算 add 函数的执行时间

import time
def add(a,b):
    start_time=time.time()
    res=a+b
    exec_time=time.time()-start_time
    return res

然后又计算sub函数的执行时间,如果不使用装饰器

​
import time
def add(a,b):
    start_time=time.time()
    res=a-b
    exec_time=time.time()-start_time
    return res

如果使用装饰器,就可以减少sub函数前后的重复代码

import tima

# 定义装饰器
def time_calc(func):
    def wrapper(*args,**kargs):
        start_time=time.time()
        f=func(*args,**kargs) # 执行“原函数”,并得到函数执行结果
        exec_time=time.time()-start_time
        return f # 返回原函数的执行结果到return wrapper
    return wrapper # 返回收到的结果到“原函数”

# 函数传入time_calc的参数后,先不执行wrapper函数,而是先return wrapper,
# 即开始执行wrapper函数,同时“原函数”的参数a、b传入*args,**kargs

# 使用装饰器
@time_calc
def add(a,b):
    return a+b

@time_calc:
    return a-b

2、作用:增强函数的功能,确切的说,可以装饰函数,也可以装饰类。

3、原理:函数是python的一等公民,函数也是对象。

4、使用装饰器

1)装饰器自身不传入参数(采用两层函数定义装饰器)

def login(func):
    def wrapper(*args,**kargs):
        print('函数名:%s'%func.__name__)
        return func(*args,**kargs)
    return wrapper

@login
def f():
    print('函数本身:inside decorator!')

f()

# 输出
# 函数名:f
# 函数本身:inside decorator!

2)装饰器自身传入参数(采用三层函数定义装饰器)

def login(text):
    def decorator(func):
        def wrapper(*args,**kargs):
            print('%s---%s'%(text,func.__name__))
            return func(*args,**kargs)
        return wrapper
    return decorator

# 一层一层往里执行,最后再一层一层往外返回

@login('this is a parameter of decorator')
def f():
    print('2020-07-24')

f()

# 输出
# this is a parameter of decorator---f
# 2020-07-24

5、内置装饰器

常见的内置装饰器:

1)@property:把类内方法当成属性来使用,必须要有返回值,相当于getter;

2)@staticmethod:静态方法。与普通方法类似,参数里面不用self,若此方法和类相关,但又不需要类和实例中的任何信息、属性等,就可以选择静态方法。比如我们检查是否开启了日志功能,这个和类相关,但是跟类的属性和实例都没有关系。

# -*- coding:utf-8 -*-
log_enabled = True

class A:
    class_attr = "attr"
    
    def __init__(self):
        pass
        
    @staticmethod
    def static_foo():
        if log_enabled:
            print("log is enabled")
        else:
            print("log is disabled")
        

A.static_foo()

3)@classmethod:类方法。当我们只需和类直接进行交互,而不需要和实例进行交互时,类方法是最好的选择。类方法与实例方法类似,但是传递的不是类的实例,而是类本身,第一个参数是cls我们可以用类的实例调用类方法,也可以直接用类名来调用。

# -*- coding:utf-8 -*-
class A:
    class_attr = "attr"
    
    def __init__(self):
        pass
        
    @classmethod
    def class_foo(cls):
        print("running class_foo(%s)" % (cls.class_attr))

a = A()
a.class_foo()
A.class_foo()

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值