如何搞懂python中的装饰器

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

装饰器的原理:函数是python的一等公民,函数也是对象。

定义装饰器

def decorator(func):
    def wrapper(*args,**kargs): 
        # 可以自定义传入的参数        
        print(func.__name__)
        # 返回传入的方法名参数的调用
        return func(*args,**kargs) 
    # 返回内层函数函数名
    return wrapper

使用装饰器

假设decorator是定义好的装饰器。

方法一:不用语法糖@符号

# 装饰器不传入参数时
f = decorator(函数名)

# 装饰器传入参数时
f = (decorator(参数))(函数名)  

方法二:采用语法糖@符号​​​​​​​

# 已定义的装饰器
@decorator 
def f():  
    pass

# 执行被装饰过的函数 
f() 

装饰器可以传参,也可以不用传参。

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

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!

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

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(text))(f) ==> 返回 wrapper  
@login('this is a parameter of decorator')  
def f():    
    print('2019-06-13')

# 等价于 ==> (login(text))(f)() ==> 调用 wrapper() 并返回 f()    
f() 

# 输出:
# => this is a parameter of decorator----f
# => 2019-06-13

内置装饰器

常见的内置装饰器有三种,@property、@staticmethod、@classmethod

@property

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

假如没有定义 @func.setter 修饰方法的话,就是只读属性

class Car:

    def __init__(self, name, price):
        self._name = name
        self._price = price    
     
    @property
    def car_name(self):
        return self._name
        
     # car_name可以读写的属性   
     @car_name.setter
     def car_name(self, value):
         self._name = value
         
     # car_price是只读属性 
     @property
     def car_price(self):
         return str(self._price) + '万'
         
benz = Car('benz', 30)

print(benz.car_name)   # benz
benz.car_name = "baojun"
print(benz.car_name)   # baojun
print(benz.car_price)  # 30万

@staticmethod

静态方法,不需要表示自身对象的self和自身类的cls参数,就跟使用函数一样。

@classmethod

类方法,不需要self参数,但第一个参数需要是表示自身类的cls参数。

例子

class Demo(object):

    text = "三种方法的比较"
    
    def instance_method(self):
        print("调用实例方法")

    @classmethod
    def class_method(cls):
        print("调用类方法")
        print("在类方法中 访问类属性 text: {}".format(cls.text))
        print("在类方法中 调用实例方法 instance_method: {}".format(cls().instance_method()))

    @staticmethod
    def static_method():
        print("调用静态方法")
        print("在静态方法中 访问类属性 text: {}".format(Demo.text))
        print("在静态方法中 调用实例方法 instance_method: {}".format(Demo().instance_method()))

if __name__ == "__main__":
    # 实例化对象
    d = Demo()
    
    # 对象可以访问 实例方法、类方法、静态方法
    # 通过对象访问text属性
    print(d.text)
    
    # 通过对象调用实例方法
    d.instance_method()
    
    # 通过对象调用类方法
    d.class_method()
    
    # 通过对象调用静态方法
    d.static_method()
    
    # 类可以访问类方法、静态方法
    # 通过类访问text属性
    print(Demo.text)
    
    # 通过类调用类方法
    Demo.class_method()
    
    # 通过类调用静态方法
    Demo.static_method()

@staticmethod 和 @classmethod 的 区别 和 使用场景

在上述例子中,我们可以看出,

区别

在定义静态类方法和类方法时,@staticmethod 装饰的静态方法里面,想要访问类属性或调用实例方法,必须需要把类名写上;

@classmethod装饰的类方法里面,会传一个cls参数,代表本类,这样就能够避免手写类名的硬编码。

在调用静态方法和类方法时,实际上写法都差不多,一般都是通过 类名.静态方法() 或 类名.类方法()。

也可以用实例化对象去调用静态方法和类方法但为了和实例方法区分,最好还是用类去调用静态方法和类方法。

使用场景

所以,在定义类的时候,

假如不需要用到与类相关的属性或方法时,就用静态方法@staticmethod

假如需要用到与类相关的属性或方法,然后又想表明这个方法是整个类通用的,而不是对象特异的,就可以使用类方法@classmethod

 

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值