python - 如何使用python引用可调用装饰器对象中的对象实例?

标签 python python-2.7 decorator scoping

上下文:

我希望能够装饰函数,以便我可以跟踪它们的统计数据。使用this作为引用,我开始尝试制作自己的可调用装饰器对象。

这是我最终得到的结果:

def Stats(fn):
    Class StatsObject(object):
        def __init__(self, fn):
            self.fn = fn
            self.stats = {}

        def __call__(self, obj, *args, **kwargs):
            self.stats['times_called'] = self.stats.get('times_called', 0) + 1
            return self.fn(obj, *args, **kwargs)

    function = StatsObject(fn)
    def wrapper(self, *args **kwargs):
        return function(self, *args, **kwargs)
    return wrapper

Class MockClass(object):
    @Stats
    def mock_fn(self, *args, **kwargs):
        # do things

问题:

这实际上正确地调用了mock_fn函数,但我没有对包装函数之外的统计对象的引用。即我不能这样做:

mc = MockClass()
mc.mock_fn()
mc.mock_fn.stats
# HasNoAttribute Exception

然后我尝试更改以下代码,认识到这是一个范围问题:

来自:

    function = StatsObject(fn)
    def wrapper(self, *args **kwargs):
        return function(self, *args, **kwargs)
    return wrapper

致:

    function = StatsObject(fn)
    return function

但是我当然丢失了 self 引用(self 成为 StatsObject 实例,obj 成为第一个参数,并且 MockClass 对象自引用丢失)。

所以我明白为什么会发生第一个问题,但不会发生第二个问题。有什么方法可以将 MockClass 的自引用传递给 StatsObject __call__ 函数吗?

最佳答案

在 Python 中,函数本身实际上可以具有属性。

def Stats(fn):
    class StatsObject(object):
        def __init__(self, fn):
            self.fn = fn
            self.stats = {}

        def __call__(self, obj, *args, **kwargs):
            self.stats['times_called'] = self.stats.get('times_called', 0) + 1
            return self.fn(obj, *args, **kwargs)

    function = StatsObject(fn)
    def wrapper(self, *args **kwargs):
        return function(self, *args, **kwargs)

    # KEY LINE BELOW: make the StatsObject available outside as "stats_fn"
    wrapper.stats_fn = function

    return wrapper

class MockClass(object):
    @Stats
    def mock_fn(self, *args, **kwargs):
        # do things

关键行是将 StatsObject 实例(您可能会误导,在本地命名为 function)分配为您返回的函数的属性来自装饰器

一旦执行此操作,self.mock_fn.stats_fn.stats(不是 self.mock_fn()!该属性位于函数上,而不是其返回值)将在 MockClass 的实例内工作,并且 MockClass.mock_fn.stats_fn.stats 将在外部可用。统计信息将在 MockClass 的所有实例中是全局的(因为装饰器被调用一次,而不是每个实例调用一次),这可能是也可能不是您想要的。

关于python - 如何使用python引用可调用装饰器对象中的对象实例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14573127/

相关文章:

python - 使用 tensorflow 一次切片多个切片

python - 一个函数有两个装饰器,后一个函数没有按预期工作?

python - 是否有 __init__ 的装饰器包可以将参数复制到对象的字段中而无需显式赋值?

python - 将转换从 `pandas.get_dummies` 应用到新数据的简单方法?

python - 损坏的 Python 2.7 GAE 安装导致 ImportError

python - numpy.piecewise 中的多个部分

python - 与 re.findall 有问题

java - 原始装饰器的实际缺点

java - 小端到整数(或 BigInteger)

python - 使用数字序列格式化字符串以生成按 Python 中的数字排序的字符串列表