如何在Python 2.7中用另一个类装饰一个实例方法? [英] How do I decorate an instance method with another class in Python 2.7?
问题描述
在Python 2.7中,我想在类 Foo
中用一个装饰器来装饰一个实例方法 test
还有一个名为 FooTestDecorator
的类。从用户Chirstop的问题和Python 2文档的描述符HowTo指南我创建了此示例。
In Python 2.7 I'd like to decorate an instance method test
in class Foo
with a decorator that is also a class called FooTestDecorator
. From user Chirstop's question and the Python 2 docs' Descriptor HowTo guide I created this example.
似乎有一个问题,当我打印装饰的方法对象时,它的(检查?)名称是错误的,因为它被标记为一个问号,如 Foo。?
。
There seems to be an issue however, when I print my decorated method object, it's (inspected?) name is wrong because it is noted as a question mark like Foo.?
.
import types
class FooTestDecorator(object):
def __init__(self,func):
self.func=func
self.count=0
# tried self.func_name = func.func_name, but seemed to have no effect
def __get__(self,obj,objtype=None):
return types.MethodType(self,obj,objtype)
def __call__(self,*args,**kwargs):
self.count+=1
return self.func(*args,**kwargs)
class Foo:
@FooTestDecorator
def test(self,a):
print a
def bar(self,b):
print b
如果你测试它:
f=Foo()
print Foo.__dict__['test']
print Foo.test
print f.test
print Foo.__dict__['bar']
print Foo.bar
print f.bar
您会得到
<__main__.FooTestDecorator ...object...>
<unbound method Foo.?>
<bound method Foo.? of ...instance...>
<function bar at 0x...>
<unbound method Foo.bar>
<bound method Foo.bar of ...instance...>
您可以看到替换方法显示为 Foo。
。这似乎是错误的。
You can see the replacement method is shown as Foo.?
. This seems wrong.
我如何获得类装饰的实例方法?
注意:我的原因是我想使用 FooDecorator
实例的 self
在里面。
note: My reason is that I want to use variables from the FooDecorator
instance's self
which I would set at init. I didn't put this in the example to keep it simpler.
推荐答案
您的装饰器实例没有 __name __
属性,因此Python与问号相关。
Your decorator instance has no __name__
attribute, so Python has to do with a question mark instead.
使用 functools.update_wrapper()
复制函数名称一些其他有趣的特殊属性(如docstring,函数模块名称以及函数可能具有的任何自定义属性):
Use functools.update_wrapper()
to copy over the function name, plus a few other interesting special attributes (such as the docstring, the function module name and any custom attributes the function may have):
import types
from functools import update_wrapper
class FooTestDecorator(object):
def __init__(self,func):
self.func=func
self.count=0
update_wrapper(self, func)
def __get__(self,obj,objtype=None):
return types.MethodType(self,obj,objtype)
def __call__(self,*args,**kwargs):
self.count+=1
return self.func(*args,**kwargs)
演示:
>>> f=Foo()
>>> print Foo.__dict__['test']
<__main__.FooTestDecorator object at 0x11077e210>
>>> print Foo.test
<unbound method Foo.test>
>>> print f.test
<bound method Foo.test of <__main__.Foo instance at 0x11077a830>>
这篇关于如何在Python 2.7中用另一个类装饰一个实例方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!