问题描述
我想实现 decorator模式在Python中,我是否想知道是否有办法编写一个只能实现要修改功能的装饰器,而无需为所有刚刚转发到装饰对象的功能编写锅炉板.喜欢:
class foo(object): def f1(self): print "original f1" def f2(self): print "original f2" class foo_decorator(object): def __init__(self, decoratee): self._decoratee = decoratee def f1(self): print "decorated f1" self._decoratee.f1() def f2(self): # I would like to leave that part out self._decoratee.f2()
我想自动打电话给foo_decorator.f2 foo_decorator.f2.有没有办法编写通用方法,将所有未完成的函数呼叫转发到decoratee?
推荐答案
您可以使用__getattr__:
class foo(object): def f1(self): print "original f1" def f2(self): print "original f2" class foo_decorator(object): def __init__(self, decoratee): self._decoratee = decoratee def f1(self): print "decorated f1" self._decoratee.f1() def __getattr__(self, name): return getattr(self._decoratee, name) u = foo() v = foo_decorator(u) v.f1() v.f2()
其他推荐答案
作为菲利普答案的附录;如果您不仅需要装饰,还需要保留对象的 type ,Python允许您在运行时为实例子类:
class foo(object): def f1(self): print "original f1" def f2(self): print "original f2" class foo_decorator(object): def __new__(cls, decoratee): cls = type('decorated', (foo_decorator, decoratee.__class__), decoratee.__dict__) return object.__new__(cls) def f1(self): print "decorated f1" super(foo_decorator, self).f1() u = foo() v = foo_decorator(u) v.f1() v.f2() print 'isinstance(v, foo) ==', isinstance(v, foo)
这比您的示例严格涉及的要多一些,您知道该课程已提前装饰.
这个可能就足够了:
class foo_decorator(foo): def __init__(self, decoratee): self.__dict__.update(decoratee.__dict__) def f1(self): print "decorated f1" super(foo_decorator, self).f1()
其他推荐答案
可以说不是最好的做法,但是您可以在实例中添加功能,因为我为帮助我的代码从Django的ORM过渡到Sqlalachemy,如下所示:
def _save(self): session.add(self) session.commit() setattr(Base,'save',_save)
问题描述
I want to implement the decorator pattern in Python, and I wondered if there is a way to write a decorator that just implements the function it wants to modify, without writing boiler-plate for all the functions that are just forwarded to the decorated object. Like so:
class foo(object): def f1(self): print "original f1" def f2(self): print "original f2" class foo_decorator(object): def __init__(self, decoratee): self._decoratee = decoratee def f1(self): print "decorated f1" self._decoratee.f1() def f2(self): # I would like to leave that part out self._decoratee.f2()
I would like to have calls to foo_decorator.f2 forwarded to decoratee.f2 automatically. Is there a way to write a generic method that forwards all unimplemented function-calls to decoratee?
推荐答案
You could use __getattr__:
class foo(object): def f1(self): print "original f1" def f2(self): print "original f2" class foo_decorator(object): def __init__(self, decoratee): self._decoratee = decoratee def f1(self): print "decorated f1" self._decoratee.f1() def __getattr__(self, name): return getattr(self._decoratee, name) u = foo() v = foo_decorator(u) v.f1() v.f2()
其他推荐答案
As an addendum to Philipp's answer; if you need to not only decorate, but preserve the type of an object, Python allows you to subclass an instance at runtime:
class foo(object): def f1(self): print "original f1" def f2(self): print "original f2" class foo_decorator(object): def __new__(cls, decoratee): cls = type('decorated', (foo_decorator, decoratee.__class__), decoratee.__dict__) return object.__new__(cls) def f1(self): print "decorated f1" super(foo_decorator, self).f1() u = foo() v = foo_decorator(u) v.f1() v.f2() print 'isinstance(v, foo) ==', isinstance(v, foo)
This is a bit more involved than strictly necessary for your example, where you know the class being decorated in advance.
This might suffice:
class foo_decorator(foo): def __init__(self, decoratee): self.__dict__.update(decoratee.__dict__) def f1(self): print "decorated f1" super(foo_decorator, self).f1()
其他推荐答案
It's arguably not the best practice, but you can add functionality to instances, as I've done to help transition my code from Django's ORM to SQLAlachemy, as follows:
def _save(self): session.add(self) session.commit() setattr(Base,'save',_save)