在Python中从子类访问父类的装饰器
怎么在子类中访问父类的装饰器呢?
我之前以为这样做就可以了:
class baseclass(object):
def __init__(self):
print 'hey this is the base'
def _deco(func):
def wrapper(*arg):
res = func(*arg)
print 'I\'m a decorator. This is fabulous, but that colour, so last season sweetiedarling'
return res
return wrapper
@_deco
def basefunc(self):
print 'I\'m a base function'
这个类运行得很好,但当我创建一个继承自这个类的子类时:
class otherclass(baseclass):
def __init__(self):
super(otherclass, self).__init__()
print 'other class'
@_deco
def meh(self):
print 'I\'m a function'
这个子类根本无法正常导入,更别提运行了。@_deco是未定义的。尝试使用baseclass._deco会出现一个未绑定的方法 _deco() 错误,这其实也不意外。
有没有什么办法可以做到这一点?我真的很想把装饰器封装在类里面,但我并不执着于这个想法,我需要在父类和子类中都能调用它。
2 个回答
3
在子类中使用这个装饰器而不提到父类,确实有一种专门针对Python3的方法,正如原问题所提到的。这需要在父类的元类中实现这个装饰器(关于元类的详细解释可以在这里找到),并使用它的__prepare__()方法。
aaronasterling的回答是解决这个问题的有效且推荐的方法,我发布这个内容只是作为一个有趣的例子,帮助其他人理解语言的基础知识。只有在没有其他方法可以实现你需要的功能时,才使用元类!
class metaclass(type):
@classmethod
def __prepare__(metacls, name, bases):
def _deco(func):
def wrapper(*arg):
res = func(*arg)
print('I\'m a decorator. This is fabulous, but that colour, so last season sweetiedarling')
return res
return wrapper
return {"_deco": _deco}
class baseclass(metaclass=metaclass):
def __init__(self):
print('hey this is the base')
@_deco
def basefunc(self):
print('I\'m a base function')
class otherclass(baseclass):
def __init__(self):
super(otherclass, self).__init__()
print('other class')
@_deco
def meh(self):
print('I\'m a function')
下面的示例代码在Python3中运行良好:
>>> obj = otherclass()
hey this is the base
other class
>>> obj.meh()
I'm a function
I'm a decorator. This is fabulous, but that colour, so last season sweetiedarling
关于__prepare__()方法的重要说明:
- 如果存在,它会在对象主体执行之前运行
- 它的返回值会作为类主体评估开始时的局部命名空间(这样,装饰器可以在子类的主体中使用,而不需要使用父类的命名空间)
- 它应该被实现为classmethod(),并且应该返回一个映射对象(例如
dict
) - 如果没有这个方法,则会使用空映射作为初始局部命名空间。
15
在编程中,有时候我们需要从一个地方获取数据,然后把这些数据放到另一个地方。这个过程就像是把水从一个杯子倒到另一个杯子一样简单。
有些时候,我们会遇到一些问题,比如数据的格式不对,或者我们想要的数据不在我们想象的地方。这就像是你想喝水,但杯子里却是果汁,这时候你就需要先把果汁倒掉,再装水。
为了避免这些麻烦,我们可以使用一些工具和方法来帮助我们更顺利地获取和处理数据。就像在厨房里使用不同的器具来做饭一样,选择合适的工具可以让我们的工作变得更轻松。
总之,处理数据的过程可能会遇到各种各样的问题,但只要我们掌握了一些基本的方法和技巧,就能更好地应对这些挑战。
class baseclass(object):
def __init__(self):
print 'hey this is the base'
def _deco(func):
def wrapper(*arg):
res = func(*arg)
print 'I\'m a decorator. This is fabulous, but that colour, so last season sweetiedarling'
return res
return wrapper
@_deco
def basefunc(self):
print 'I\'m a base function'
@_deco
def basefunc2(self):
print "I'm another base function"
#no more uses of _deco in this class
_deco = staticmethod(_deco)
# this is the key. it must be executed after all of the uses of _deco in
# the base class. this way _deco is some sort weird internal function that
# can be called from within the class namespace while said namespace is being
# created and a proper static method for subclasses or external callers.
class otherclass(baseclass):
def __init__(self):
super(otherclass, self).__init__()
print 'other class'
@baseclass._deco
def meh(self):
print 'I\'m a function'