gpt4 book ai didi

python - 如何计算方法调用,但不计算属性访问?

转载 作者:行者123 更新时间:2023-11-30 22:00:31 25 4
gpt4 key购买 nike

我正在为多个类准备一个父类,从它的角度来看,我需要知道是否调用了特定的实例方法。

我开始做这样的事情:

from collections import defaultdict
class ParentClass:
def __init__(self, ):
self.call_count = defaultdict(int)

def __getattribute__(self, item):
if item != 'call_count':
self.call_count[item] += 1
return object.__getattribute__(self, item)


class ChildClass(ParentClass):
def child_method(self):
pass

不幸的是,call_count 还包括访问该字段,但不调用它:

ob = ChildClass()

ob.child_method()
ob.child_method

assert ob.call_count['child_method'] == 1 # it's 2

我如何从对象实例检测到它的字段正在被调用(不仅仅是访问)?

最佳答案

使用自定义元类的(python3)解决方案:

from collections import defaultdict
from functools import wraps
import inspect

def count_calls(func):
name = func.__name__

@wraps(func)
def wrapper(self, *args, **kwargs):
# creates the instance counter if necessary
counter = getattr(self, "_calls_counter", None)
if counter is None:
counter = self._calls_counter = defaultdict(int)
counter[name] += 1
return func(self, *args, **kwargs)

wrapper._is_count_call_wrapper = True
return wrapper


class CallCounterType(type):
def __new__(cls, name, bases, attrs):
for name, attr in attrs.items():
if not inspect.isfunction(attr):
# this will weed out any callable that is not truly a function
# (including nested classes, classmethods and staticmethods)
continue

try:
argspec = inspect.getargspec(attr)
except TypeError:
# "unsupported callable" - can't think of any callable
# that might have made it's way until this point and not
# be supported by getargspec but well...
continue

if not argspec.args:
# no argument so it can't be an instancemethod
# (to be exact: a function designed to be used as instancemethod)
# Here again I wonder which function could be found here that
# doesn't take at least `self` but anyway...
continue

if getattr(attr, "_is_count_call_wrapper", False):
# not sure why we would have an already wrapped func here but etc...
continue

# ok, it's a proper function, it takes at least one positional arg,
# and it's not already been wrapped, we should be safe
attrs[name] = count_calls(attr)

return super(CallCounterType, cls).__new__(cls, name, bases, attrs)


class ParentClass(metaclass=CallCounterType):
pass

class ChildClass(ParentClass):
def child_method(self):
pass

请注意,在实例上存储调用计数仅允许对实例方法调用进行计数,显然......

关于python - 如何计算方法调用,但不计算属性访问?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54286537/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com