如何创建实例特定的函数计数器?
How to create instance specific function counter?
我想跟踪 class 中的函数计数,但 class 的每个实例的计数都不同。
我们可以在一个简单的函数上设置一个计数器:
def foo1():
pass
foo1.count = 0
foo1.count +=1
print(foo1.count)
现在让我们转向 class 方法:
class A:
def foo2(self):
print('Hi')
这里也可以设置计数器
A.foo2.count = 0
a = A()
b = A()
但此计数不是特定于实例的
A.foo2.count += 1
print(a.foo2.count)
print(b.foo2.count)
无法为 INSTANCE 方法设置计数:
a.foo2.count += 1
如果我们使用 __func__
则相当于更改 A.foo2.count
:
a.foo2.__func__.count += 1
print(b.foo2.count)
print(a.foo2.count)
print(A.foo2.count)
问题:如何使foo2.count
INSTANCE具体化?这样 a
和 b
可以有多个值 foo2.count
?
请注意:我问的是 function 属性,而不是 class 属性。
使用__init__
方法:
class A:
def __init__(self):
self.count_foo2 = 0
def foo2(self):
print('Hi')
self.count_foo2 += 1
a = A()
b = A()
a.foo2()
print(a.count_foo2)
print(b.count_foo2)
输出:
Hi
1
0
也许是这样?
from collections import defaultdict
def foo1():
print('Hi')
foo1.count = defaultdict(int)
class A:
def foo2(self):
foo1()
foo1.count[self] += 1
a = A()
b = A()
a.foo2()
a.foo2()
b.foo2()
print(foo1.count)
输出:
Hi
Hi
Hi
defaultdict(<class 'int'>, {<__main__.A object at 0x000001E59759ABE0>: 2, <__main__.A object at 0x000001E596AFCD30>: 1})
这是我的尝试。我不确定这是否完全是您想要的,因为在您的评论之一中您表示您想要特定的函数实例属性(?)。然而,这似乎 表现 您所描述的方式。无论您希望此行为发生多少方法,它都有工作的好处。
def fn_exec_count(base_fn):
def new_fn(self, *args, **kwargs):
fn_count_attr = 'fn_' + base_fn.__name__ + '_count'
if not hasattr(self, fn_count_attr):
setattr(self, fn_count_attr, 1)
else:
setattr(self, fn_count_attr, getattr(self, fn_count_attr) + 1)
base_fn(self, *args, **kwargs)
new_fn.__name__ = base_fn.__name__
return new_fn
class A:
@fn_exec_count
def foo(self):
fn_count_attr = 'fn_' + A.foo.__name__ + '_count'
print(f'Value of counter: {getattr(self, fn_count_attr, None)}')
a1 = A()
a1.foo()
a1.foo()
a2 = A()
a2.foo()
a1.foo()
输出:
Value of counter: 1
Value of counter: 2
Value of counter: 1
Value of counter: 3
编辑:从 Julien 的使用 defaultdict 的答案中窃取内容使这稍微不那么冗长。
def fn_exec_count_dict(base_fn):
def new_fn(self, *args, **kwargs):
if not hasattr(self, 'fn_exec_count'):
setattr(self, 'fn_exec_count', defaultdict(int))
self.fn_exec_count[base_fn.__name__] += 1
base_fn(self, *args, **kwargs)
new_fn.__name__ = base_fn.__name__
return new_fn
class A:
@fn_exec_count_dict
def foo(self):
print(f'Value of counter: {self.fn_exec_count[A.foo.__name__]}')
# ...
我想跟踪 class 中的函数计数,但 class 的每个实例的计数都不同。
我们可以在一个简单的函数上设置一个计数器:
def foo1():
pass
foo1.count = 0
foo1.count +=1
print(foo1.count)
现在让我们转向 class 方法:
class A:
def foo2(self):
print('Hi')
这里也可以设置计数器
A.foo2.count = 0
a = A()
b = A()
但此计数不是特定于实例的
A.foo2.count += 1
print(a.foo2.count)
print(b.foo2.count)
无法为 INSTANCE 方法设置计数:
a.foo2.count += 1
如果我们使用 __func__
则相当于更改 A.foo2.count
:
a.foo2.__func__.count += 1
print(b.foo2.count)
print(a.foo2.count)
print(A.foo2.count)
问题:如何使foo2.count
INSTANCE具体化?这样 a
和 b
可以有多个值 foo2.count
?
请注意:我问的是 function 属性,而不是 class 属性。
使用__init__
方法:
class A:
def __init__(self):
self.count_foo2 = 0
def foo2(self):
print('Hi')
self.count_foo2 += 1
a = A()
b = A()
a.foo2()
print(a.count_foo2)
print(b.count_foo2)
输出:
Hi
1
0
也许是这样?
from collections import defaultdict
def foo1():
print('Hi')
foo1.count = defaultdict(int)
class A:
def foo2(self):
foo1()
foo1.count[self] += 1
a = A()
b = A()
a.foo2()
a.foo2()
b.foo2()
print(foo1.count)
输出:
Hi
Hi
Hi
defaultdict(<class 'int'>, {<__main__.A object at 0x000001E59759ABE0>: 2, <__main__.A object at 0x000001E596AFCD30>: 1})
这是我的尝试。我不确定这是否完全是您想要的,因为在您的评论之一中您表示您想要特定的函数实例属性(?)。然而,这似乎 表现 您所描述的方式。无论您希望此行为发生多少方法,它都有工作的好处。
def fn_exec_count(base_fn):
def new_fn(self, *args, **kwargs):
fn_count_attr = 'fn_' + base_fn.__name__ + '_count'
if not hasattr(self, fn_count_attr):
setattr(self, fn_count_attr, 1)
else:
setattr(self, fn_count_attr, getattr(self, fn_count_attr) + 1)
base_fn(self, *args, **kwargs)
new_fn.__name__ = base_fn.__name__
return new_fn
class A:
@fn_exec_count
def foo(self):
fn_count_attr = 'fn_' + A.foo.__name__ + '_count'
print(f'Value of counter: {getattr(self, fn_count_attr, None)}')
a1 = A()
a1.foo()
a1.foo()
a2 = A()
a2.foo()
a1.foo()
输出:
Value of counter: 1
Value of counter: 2
Value of counter: 1
Value of counter: 3
编辑:从 Julien 的使用 defaultdict 的答案中窃取内容使这稍微不那么冗长。
def fn_exec_count_dict(base_fn):
def new_fn(self, *args, **kwargs):
if not hasattr(self, 'fn_exec_count'):
setattr(self, 'fn_exec_count', defaultdict(int))
self.fn_exec_count[base_fn.__name__] += 1
base_fn(self, *args, **kwargs)
new_fn.__name__ = base_fn.__name__
return new_fn
class A:
@fn_exec_count_dict
def foo(self):
print(f'Value of counter: {self.fn_exec_count[A.foo.__name__]}')
# ...