python装饰器

1、函数装饰器

 函数装饰器 -- 就是将一个函数作为另一个函数的输入,实际上即为已经存在的函数或对象添加额外的功能;

a)不带参数的装饰器:

def debug(func):
    def wrapper():
        print("[DEBUG]: enter {}()".format(func.__name__))   #输出func的函数名
        return func()
    return wrapper

@debug
def say_hello():
    print("hello!")

if __name__ == '__main__':
    say_hello()

b) 带固定参数的装饰器:

def debug(func):
    def wrapper(name):
        print("[DEBUG]: enter {}()".format(func.__name__))   #输出func的函数名
        return func(name)
    return wrapper

@debug
def say(name):
    print("hello {}!".format(name))

if __name__ == '__main__':
    say("Hanmeimei")

c) 带不定参数的装饰器:

def debug(func):
    def wrapper(*args,**kwargs):     #带不定参数
        print("[DEBUG]: enter {}()".format(func.__name__))   #输出func的函数名
        return func(*args,**kwargs)
    return wrapper

@debug
def say(*args,**kwargs):    #*args 表示函数参数是任意多个,会被封装成tuple,**kwargs表示参数是字典,会被封装成键值对
    print(args)
    print(kwargs)

if __name__ == '__main__':
    say('Hanmeimei', 'Lilei', a1="Bob", a2="Amy")

 

2、类装饰器 -- 相比函数装饰器,类装饰器具有灵活度大、封装性等优点。使用类装饰器还可以依靠类内部的__call__方法,当使用@形式将装饰器附加到函数上时,就会调用此方法。

class Foo(object):
    def __init__(self, func):
        self.func = func
    def __call__(self):
        print('类装饰器running')
        self.func()
        print('类装饰器ending')

@Foo
def bar():
    print('bar')

if __name__ == '__main__':
    bar()
    

3、内置装饰器 @property、@staticmethod、@classmethod -- 内置装饰器和普通装饰器原理相同,只不过返回的不是函数,而是类对象。

@property装饰器用来创建只读属性,将类方法变成同名的只读属性

class DataSet(object):
    def __init__(self):
        self._images = 1 #定义属性的名称
    @property
    def images(self): #方法加入@property后,这个方法相当于一个属性,这个属性可以让用户进行使用,而且用户有没办法随意修改。
        return self._images

l = DataSet()
#用户进行属性调用的时候,直接调用images即可,而不用知道属性名_images,因此用户无法更改属性,从而保护了类的属性。
print(l.images) # 加了@property后,可以用调用属性的形式来调用方法,后面不需要加()。

@staticmethod装饰器用于修改类中的方法,使其不创建类的实例就可访问,即使用类名就可访问

class DataSet(object):
    def __init__(self, s1, s2):
        self.s1 = s1
        self.s2 = s2

    # 声明一个静态方法
    @staticmethod
    def data(s1, s2):
        return s1+s2

print(DataSet.data(1, 4)) # 使用类名.方法()即可完成调用

@classmethod 依然是一种类方法,改方法可以直接被调用无需实例化,没有self参数,无法被实例化的对象调用,相对于staticmethod的区别在于它会接收一个指向类本身的cls参数

class DataSet(object):

    # 声明一个classmethod类方法
    @classmethod
    def data(cls):
        return 22

print(DataSet.data()) # 使用类名.方法()不能够被类的实例调用

 

posted @ 2021-07-08 18:09  宇宙刘  阅读(62)  评论(0)    收藏  举报