之前我们看的是函数作为装饰器,类可以作为装饰器,
被装饰的对象之前学习的都是函数,今天我们来看一下装饰器装饰类;
def test(func):
def test_in():
print("----test_in-----")
func()
return test_in
@test #Hero=test(Hero)
class Hero(object):
def fun(self):
print('----装饰器装饰类-----')
h=Hero()
print(h)
运行结果:
----test_in-----
None
发现为何执行结果为None,我们来看一下执行过程:
1.执行h=Hero()的过程实际并不是创建对象,而是相当于去执行装饰器;执行Hero相当于去执行test(Hero);
2.执行test(func)时外部函数返回值为内部函数体,test_in,。此时会去执行test_in()
3.test_in的返回值会指向h,但是内部函数test_in没有返回值,所以打印h会输出None;
我们想要在执行h=Hero()时创建对象,应该在闭包中进行创建对象,即test_in函数体中进行创建对象
以上改造如下:
def test(func):
def test_in():
print("----test_in-----")
f=func() #实际是创建对象
return f #返回对象
return test_in
@test #Hero=test(Hero)
class Hero(object):
def fun(self):
print('----装饰器装饰类-----')
h=Hero()
h.fun()
运行结果:
----test_in-----
----装饰器装饰类-----
还可以装饰器中给对象设置属性:
def test(func):
def test_in():
print("----test_in-----")
setattr(func,'name','静静') #使用setattr设置属性
f=func() #实际是创建对象
return f #返回对象
return test_in
@test #Hero=test(Hero)
class Hero(object):
def fun(self):
print('----装饰器装饰类-----')
h=Hero()
h.fun()
print(h.name)
运行结果:
----test_in-----
----装饰器装饰类-----
静静
再看一下类装饰器装饰类:
class test():
def __init__(self,func):
print('----init----')
self.func=func
def __call__(self, *args, **kwargs):
print('---call---')
self.func()
@test #Hero=test(Hero)
class Hero(object):
def fun(self):
print('----装饰器装饰类-----')
h=Hero()
h.fun()
运行报错:
----init----
---call---
Traceback (most recent call last):
File "C:/workspace/pythonTest/pythonDemo/0830_deo.py", line 27, in <module>
h.fun()
AttributeError: 'NoneType' object has no attribute 'fun'
可见同样是缺少返回值:
call方法中将被装饰函数返回:
class test():
def __init__(self,func):
print('----init----')
self.func=func
def __call__(self, *args, **kwargs):
print('---call---')
return self.func() #返回
@test #Hero=test(Hero)
class Hero(object):
def fun(self):
print('----装饰器装饰类-----')
h=Hero()
h.fun()
运行结果:
----init----
---call---
----装饰器装饰类-----
可见装饰类和装饰函数的区别是:
1.类需要创建对象,因此需要将类对象返回,即需要在函数装饰器的内部函数中返回或者在类装饰器的call方法中将类对象返回;