Python--类装饰器

类装饰器

      在介绍类的装饰器之前,首先介绍一下类像函数一下运行。
      创建一个类之后,并创建该类的实例,如果想函数一下运行这个类的实例,则会报错。
如:

class Test:
	def __init__(self):
		self.a = 100
		self.b = 200
		
test = Test()
test()

则会报错:
在这里插入图片描述
      出现以上问题的原因是因为,像函数一样调用类的实例的时候,实际上调用的是类中__call__函数,而在以上的代码中我们并没有进行__call__函数的编写,导致错误。补充:__call__调用时都是在最后调用。
更给以上代码为:

class Test:
	def __init__(self):
		self.a = 100
		self.b = 200
		
	def __call__(self):
		print("我是类,我像函数一样运行")
		
test = Test()
test()

结果为:
在这里插入图片描述

用于修饰类的修饰器

      用于修饰类的修饰器,相当于把被修饰的类的引用传递到,修饰器中,并将该类的名称指向返回的类。

def Test(obj):
	obj.testadd = "我是修饰器添加的属性"
	return obj

@Test	#相当于A=obj
class A:
	def __init__(self):
		self.a = 100
		self.b = 200
		
	def __call__(self):
		print("我是类,我像函数一样运行")
		
a = A()
print(a.a)
print(a.b)
print(a.testadd)

输出结果为:
在这里插入图片描述

类作为修饰器

      类作为修饰器,被修饰的函数被传递给,类修饰器的__init__函数作为参数,然后被修饰的函数被重新指向于返回的类的实例。
如:

class Test(object):
    def __init__(self,func):
        print("-------初始化-------")
        print("func name is %s" %func.__name__)
        self.__func = func #类的私有属性self.__func也指向了test1函数的内存地址。
    def __call__(self, *args, **kwargs): #test1 = Test(test1) #调用类的对象。就会调用call方法。
        print("------装饰器中的功能-------")
        self.__func() #self.__func指向了函数test1的内存地址。这句话相当于执行test1()函数。


#使用类作为装饰器,需要重写Call方法,没有调用test1()方法的时候,执行代码得到下面的结果
# -------初始化-------
# func name is test1

@Test #相当于 test1 = Test(test1)  也相当于func指向了下面函数test1的名字, 前面的test1指向了 Test()这个对象。
# 调用test1对象的时候相当于调用类方法Test(),调用类方法必调用__call方法,调用call方法的时候,先执行    print("------装饰器中的功能-------")
#然后在执行self.__func() ,因为self.__func函数指向的是test1函数,test1()相当于执行self.__func().
def test1():
    print("----test1---------")

test1() #调用test1

输出结果为:

-------初始化-------
func name is test1
------装饰器中的功能-------
----test1---------

      类作为修饰器,修饰另一个类中方法的时候,此时的被修饰的方法,被指向类修饰器的实例,如果调用的时候则不会自动再给__call__函数传递被修饰的类的self实例。
如:

class Test(object):
    def __init__(self,func):
        print("-------初始化-------")
        #print("func name is %s" %func.__name__)
        self.__func = func #类的私有属性self.__func也指向了test1函数的内存地址。
        
    def __call__(self, *args, **kwargs): #test1 = Test(test1) #调用类的对象。就会调用call方法。
        print("------装饰器中的功能-------")
        print('aa',self)
        self.__func( *args, **kwargs) #self.__func指向了函数test1的内存地址。这句话相当于执行test1()函数。

class A:
    def __init__(self):
        self.a = 100
        self.b = 200
    @Test   #相当于sayHello=Test(sayHello)
    def sayHello(self):
        print("Hello")
        
a = A()
a.sayHello()

输出结果:
在这里插入图片描述
修改方法,可以手动传递缺少的实例:

a.sayHello(a)

也可以再次使用修饰器,使其变为可以自动传递的方法:

class Test(object):
    def __init__(self,func):
        print("-------初始化-------")
        #print("func name is %s" %func.__name__)
        self.__func = func #类的私有属性self.__func也指向了test1函数的内存地址。
        
    def __call__(self, *args, **kwargs): #test1 = Test(test1) #调用类的对象。就会调用call方法。
        print("------装饰器中的功能-------")
        print('aa',self)
        self.__func( *args, **kwargs) #self.__func指向了函数test1的内存地址。这句话相当于执行test1()函数。

def wapper(func):
    def inner(*args,**kwargs):
        return func(*args,**kwargs)
    return inner

class A:
    def __init__(self):
        self.a = 100
        self.b = 200
    @wapper
    @Test
    def sayHello(self):
        print("Hello")
        
a = A()
a.sayHello()

输出结果为:

-------初始化-------
------装饰器中的功能-------
aa <__main__.Test object at 0x0000000B8A34D828>
Hello

给类的方法使用普通修饰器

      给类的方法,使用普通修饰器的时候,由于类的方法自动传递实例的特性,需要多加一个参数,进行接受自动传递的实例。

def outer(obj):         # 类方法装饰器
    def inner(self):
        print('hello inner')
        obj(self)
 
    return inner
 
class Zoo(object):
    def __init__(self):
        pass
 
    @outer        # => zoo = outer(zoo)
    def zoo(self):
        print('hello zoo')
 
zoo = Zoo()
print(zoo.zoo.__name__)
zoo.zoo()

输出结果为:

inner
hello inner
hello zoo

用于模拟对象的装饰器–类装饰器

      装饰器中也可以闭包中含有类,使用方法与修饰类的修饰器的方法一致。

def outer(clss):         # 类装饰器
    class Inner(object):
        def __init__(self):
            self.clss = clss()
 
        def __getattr__(self, attr):
            return getattr(self.clss, attr)
 
    return Inner
 
 
@outer          # Zoo = outer(Zoo)
class Zoo(object):
    def __init__(self):
        pass
 
    def say(self):
        print('hello world!')
 
zoo = Zoo()
print(zoo.__class__)    # <class '__main__.outer.<locals>.Inner'>
zoo.say()               # hello world!

输出结果为:

<class '__main__.outer.<locals>.Inner'>
hello world!

借鉴与:
https://blog.csdn.net/qq_29767317/article/details/80799410
https://blog.csdn.net/five3/article/details/83447467

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值