Python __metaclass__ 继承问题
我的问题是,我正在使用元类将某些类方法包装在计时器中以用于记录目的。
例如:
class MyMeta(type):
@staticmethod
def time_method(method):
def __wrapper(self, *args, **kwargs):
start = time.time()
result = method(self, *args, **kwargs)
finish = time.time()
sys.stdout.write('instancemethod %s took %0.3f s.\n' %(
method.__name__, (finish - start)))
return result
return __wrapper
def __new__(cls, name, bases, attrs):
for attr in ['__init__', 'run']:
if not attr in attrs:
continue
attrs[attr] = cls.time_method(attrs[attr])
return super(MetaBuilderModule, cls).__new__(cls, name, bases, attrs)
我遇到的问题是我的包装器为每个“__init__”运行,尽管我实际上只希望它用于我正在实例化的当前模块。这同样适用于任何想要计时的方法。我不希望计时在任何继承的方法上运行,除非它们没有被覆盖。
class MyClass0(object):
__metaclass__ = MyMeta
def __init__(self):
pass
def run(self):
sys.stdout.write('running')
return True
class MyClass1(MyClass0):
def __init__(self): # I want this timed
MyClass0.__init__(self) # But not this.
pass
''' I need the inherited 'run' to be timed. '''
我尝试了一些方法,但到目前为止还没有成功。
My issue is that I am using a metaclass to wrap certain class methods in a timer for logging purposes.
For example:
class MyMeta(type):
@staticmethod
def time_method(method):
def __wrapper(self, *args, **kwargs):
start = time.time()
result = method(self, *args, **kwargs)
finish = time.time()
sys.stdout.write('instancemethod %s took %0.3f s.\n' %(
method.__name__, (finish - start)))
return result
return __wrapper
def __new__(cls, name, bases, attrs):
for attr in ['__init__', 'run']:
if not attr in attrs:
continue
attrs[attr] = cls.time_method(attrs[attr])
return super(MetaBuilderModule, cls).__new__(cls, name, bases, attrs)
The problem I'm having is that my wrapper runs for every '__init__' even though I really only want it for the current module I am instantiating. The same goes for any method want to time. I dont want the timing to run on any inherited methods UNLESS they aren't being overridden.
class MyClass0(object):
__metaclass__ = MyMeta
def __init__(self):
pass
def run(self):
sys.stdout.write('running')
return True
class MyClass1(MyClass0):
def __init__(self): # I want this timed
MyClass0.__init__(self) # But not this.
pass
''' I need the inherited 'run' to be timed. '''
I've tried a few things but so far I've had no success.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
使用属性保护计时代码。这样,只有对象上最外层的修饰方法才会真正计时。
仅对最外面的方法进行计时与“不对继承的方法进行计时,除非它们没有被覆盖”略有不同,但我相信它可以解决您的问题。
Guard the timing code with an attribute. That way, only the outermost decorated method on an object will actually get timed.
Timing only the outermost method is slightly different than “not timing inherited methods unless they aren't being overridden”, but I believe it solves your problem.
我不确定这与多重继承有什么关系。
问题是
MyClass0
的任何子类都必须是同一元类的实例,这意味着MyClass1
是用MyMeta.__new__
创建的,所以它的方法被处理并包装在计时代码中。实际上,您需要的是
MyClass0.__init__
在以下两种情况下以某种方式返回不同的内容:MyClass0
,或当MyClass1
code> 不覆盖它),它需要返回定时方法这是不可能的,因为
MyClass0.__init__
不知道为什么它被调用。我看到三个选项:
start_timing
和stop_timing
方法,如果在该方法已经计时时调用start_timing
,则只需增加一个计数器,并且stop_timing
只是递减计数器,并且仅在计数器为零时停止计时。小心调用其他定时方法的定时方法;每个方法名称需要有单独的计数器。I'm not sure this has anything to do with multiple inheritance.
The trouble is that any subclass of
MyClass0
has to be an instance of the same metaclass, which meansMyClass1
gets created withMyMeta.__new__
, so its methods get processed and wrapped in the timing code.Effectively, what you need is that
MyClass0.__init__
somehow returns something different in the two following circumstances:MyClass0
directly, or whenMyClass1
doesn't override it), it needs to return the timed methodThis is impossible, since
MyClass0.__init__
doesn't know why it's being called.I see three options:
start_timing
andstop_timing
method, and ifstart_timing
is called when the method is already being timed you just increment a counter, andstop_timing
just decrements a counter and only stops timing when the counter hits zero. Be careful of timed methods that call other timed methods; you'll need to have separate counters per method name.