3

我有一个看起来像这样的类:

class Test(object):
    data = {}

    @add_to_data(1)
    def method_1(self, x, y):
        pass

    @add_to_data(1, 2, 3)
    def method_2(self, x, y):
        pass

    @add_to_data(5, 6, 7)
    def method_3(self, x, y):
        pass

我希望它在“导入时间”时data类的属性是:

>>> Test.data
{'method_1': [1], 'method_2': [1, 2, 3], 'method_3': [5, 6, 7]}

目前我有这个(data是一个defaultdict):

def add_to_data(*items):
    def decorator(func):
        for item in items:
            name = func.__name__
            cls = ??
            cls.data[name].append(item)
        return func
    return decorator

但我不知道如何获取类对象。有什么帮助吗?

4

2 回答 2

4

它不是特别干净,但是您可以使用它sys._getframe()来检查调用范围(装饰器将在类定义的上下文中调用,其中data是局部变量。

所以像下面这样的东西应该可以工作:

import sys

def add_to_data(*items):
    def decorator(func):
        name = func.__name__
        data = sys._getframe(1).f_locals.get('data')
        if data is not None:
            data.setdefault(name, []).extend(items)
        return func
    return decorator

如果你不想依赖sys._getframe或想要更明确的东西,你可以让你的@add_to_data函数装饰器简单地用适当的函数属性标记方法,然后使用类装饰器data从所有标记的方法构建字典。

于 2012-12-14T02:33:26.763 回答
1

你不能这样做,因为类对象还不存在。

您可能可以通过创建一个基类来做类似的事情,该基类@classmethod在子类中用作装饰器,或者将东西存储在其他地方的装饰器以及data稍后将存储复制到类的属性中的类装饰器或元类。

好吧,真的,不知道你的实际目标是什么——以及你是使用 Py2 还是 Py3(以及你是否只关心 CPython 或任何 Python)——很难知道该建议什么。

于 2012-12-14T02:33:14.300 回答