python调用另一个python程序,当调用另一个方法时,Python类方法运行

这篇博客讨论了如何在Python类中跟踪方法的调用次数。现有的方法是通过在每个方法内部手动调用`addMethodCall()`来增加计数。然而,没有内置的方法在每次方法被调用时自动触发。作者提出两种解决方案:一是使用装饰器为每个需要计数的方法增加计数;二是利用元类在类创建时自动装饰所有函数。装饰器方案需要手动应用到每个方法,而元类方案则能自动处理。
摘要由CSDN通过智能技术生成

I have a class as follows:

class MyClass(object):

def __init__(self):

self.foo = "foo"

self.bar = "bar"

self.methodCalls = 0 #tracks number of times any function in the instance is run

def get_foo(self):

addMethodCall()

return self.foo

def get_bar(self):

addMethodCall()

return self.bar

def addMethodCall(self):

self.methodCalls += 1

Is there an inbuilt function that is invoked whenever a method is invoked instead of constantly running addMethodCall()?

解决方案

No, there are no hooks on a class to do this. Methods are attributes too, albeit somewhat special in that they are produced when accessing the function object on the instance; functions are descriptors.

The call to a method object is then a separate step from producing the method object:

>>> class Foo(object):

... def bar(self):

... return 'bar method on Foo'

...

>>> f = Foo()

>>> f.bar

>

>>> f.bar is f.bar

False

>>> stored = f.bar

>>> stored()

'bar method on Foo'

It is the task of the object.__getattribute__() method to invoke the descriptor protocol, so you could hook into that to see when a method is produced, but you'd still need to wrap that produced method object to detect calls. You could return an object with a __call__ method that proxies for the actual method for example.

However, it'd be easier to decorate each method with a decorator that increments a counter every time it is called. Take into account decorators apply to a function before it is bound, so you'll have to pass self along:

from functools import wraps

def method_counter(func):

@wraps(func)

def wrapper(self, *args, **kwargs):

self.methodCalls += 1

return func(self, *args, **kwargs)

return wrapper

You'd still need to apply this to all functions in your class. You could apply this manually to all methods you want to count:

class MyClass(object):

def __init__(self):

self.foo = "foo"

self.bar = "bar"

self.methodCalls = 0 #tracks number of times any function method is run

@method_counter

def get_foo(self):

return self.foo

@method_counter

def get_bar(self):

return self.bar

or you could use a metaclass:

import types

class MethodCounterMeta(type):

def __new__(mcls, name, bases, body):

# create new class object

for name, obj in body.items():

if name[:2] == name[-2:] == '__':

# skip special method names like __init__

continue

if isinstance(obj, types.FunctionType):

# decorate all functions

body[name] = method_counter(obj)

return super(MethodCounterMeta, mcls).__new__(mcls, name, bases, body)

def __call__(cls, *args, **kwargs):

# create a new instance for this class

# add in `methodCalls` attribute

instance = super(MethodCounterMeta, cls).__call__(*args, **kwargs)

instance.methodCalls = 0

return instance

This takes care of everything the decorator needs, setting a methodCalls attribute for you, so your class doesn't have to:

class MyClass(object):

__metaclass__ = MethodCounterMeta

def __init__(self):

self.foo = "foo"

self.bar = "bar"

def get_foo(self):

return self.foo

def get_bar(self):

return self.bar

Demo of the latter approach:

>>> class MyClass(object):

... __metaclass__ = MethodCounterMeta

... def __init__(self):

... self.foo = "foo"

... self.bar = "bar"

... def get_foo(self):

... return self.foo

... def get_bar(self):

... return self.bar

...

>>> instance = MyClass()

>>> instance.get_foo()

'foo'

>>> instance.get_bar()

'bar'

>>> instance.methodCalls

2

The above metaclass only considers function objects (so the result of def statements and lambda expressions) part of the class body for decoration. It ignores any other callable objects (there are more types that have a __call__ method, such as functools.partial objects), as are functions added to the class later on.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值