gpt4 book ai didi

python - 以侵入性最小、最隐形的方式检测对象使用情况

转载 作者:行者123 更新时间:2023-12-01 01:05:22 25 4
gpt4 key购买 nike

有没有办法自动检测 python 对象何时被使用(并可能对此使用react)?

例如,假设我有一个 Foo 类型的对象。我没有为 Foo 编写类代码,因为它来自外部库。

我想以这样的方式“装饰”我的对象,每当使用其方法之一,或者每当其内部状态(成员)更改或访问时,我都会得到一些日志信息,例如” Foo 正在使用”

我使用“装饰”术语来强调我不想更改使用 Foo 类型对象的所有接口(interface)。我只是想为其添加一些功能。

此外,我还避免直接修改 Foo 的类代码,即通过在其每个方法的开头显式添加 print 语句(无论哪种方式)这不会通知我其成员何时发生变化)。

而且我不想将我的对象显式注册到其他一些对象,因为这将是一种“侵入性”方法,需要更改“客户端”代码(使用 Foo 的代码 对象),这将是很容易被忘记的东西。

最佳答案

我可以想到一个解决方案,它并不完美,但它可能是一个开始。我们可以在从装饰类继承的类中通过 __getattribute____setattribute__ 捕获实例属性访问:

import re

dunder_pattern = re.compile("__.*__")
protected_pattern = re.compile("_.*")

def is_hidden(attr_name):
return dunder_pattern.match(attr_name) or protected_pattern.match(attr_name)


def attach_proxy(function=None):
function = function or (lambda *a: None)

def decorator(decorated_class):

class Proxy(decorated_class):
def __init__(self, *args, **kwargs):
function("init", args, kwargs)
super().__init__(*args, **kwargs)

def __getattribute__(self, name):
if not is_hidden(name):
function("acces", name)
return object.__getattribute__(self, name)

def __getattr__(self, name):
if not is_hidden(name):
function("acces*", name)
return object.__getattr__(self, name)

def __setattribute__(self, name, value):
if not is_hidden(name):
function("set", name, value)
return object.__setattribute__(self, name, value)

def __setattr__(self, name, value):
if not is_hidden(name):
function("set*", name, value)
return object.__setattr__(self, name, value)

return Proxy

return decorator

然后你可以用它来装饰你的类:

@attach_proxy(print)
class A:
x = 1
def __init__(self, y, msg="hello"):
self.y = y

@classmethod
def foo(cls):
print(cls.x)

def bar(self):
print(self.y)

这将导致以下结果:

>>> a = A(10, msg="test")
init (10,) {'msg': 'test'}
set* y 10
>>> a.bar()
acces bar
acces y
10
>>> a.foo() # access to x is not captured
acces foo
1
>>> y = a.y
acces y
>>> x = A.x # access to x is not captured
>>> a.y = 3e5
set* y 300000.0

问题:

  1. 未捕获类属性访问(需要一个元类,但我看不到即时执行的方法)。

  2. 类型A被隐藏(在类型Proxy后面),这可能更容易解决:

>>> A
__main__.attach_proxy.<locals>.decorator.<locals>.Proxy

另一方面,这不一定是问题,因为它会按预期工作:

>>> a = A(10, msg="test")
>>> isinstance(a, A)
True

编辑请注意,我不会将实例传递给 function 调用,但这实际上是一个好主意,替换来自 function("acces"的调用, name)function("access", self, name)。这将允许你用你的装饰器做出更多有趣的事情。

关于python - 以侵入性最小、最隐形的方式检测对象使用情况,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55413650/

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