python decorator修改当前范围内的变量

Ale*_*exH 4 python scope decorator

目标:制作一个可以修改其使用范围的装饰器.

如果有效:

class Blah(): # or perhaps class Blah(ParentClassWhichMakesThisPossible)

    def one(self):
        pass

    @decorated
    def two(self):
        pass

>>> Blah.decorated
["two"]
Run Code Online (Sandbox Code Playgroud)

为什么?我本质上想要编写可以维护特定字典方法的类,这样我就可以在每个类的基础上检索不同类型的可用方法的列表.errr .....

我想做这个:

class RuleClass(ParentClass):
    @rule
    def blah(self):
        pass

    @rule
    def kapow(self):
        pass

    def shazam(self):

class OtherRuleClass(ParentClass):
    @rule
    def foo(self):
        pass

    def bar(self):
        pass

>>> RuleClass.rules.keys()
["blah", "kapow"]
>>> OtherRuleClass.rules.keys()
["foo"]
Run Code Online (Sandbox Code Playgroud)

Tho*_*ers 9

您可以使用类装饰器(在Python 2.6中)或元类来执行您想要的操作.类装饰器版本:

def rule(f):
    f.rule = True
    return f

def getRules(cls):
    cls.rules = {}
    for attr, value in cls.__dict__.iteritems():
        if getattr(value, 'rule', False):
            cls.rules[attr] = value
    return cls

@getRules
class RuleClass:
    @rule
    def foo(self):
        pass
Run Code Online (Sandbox Code Playgroud)

元类版本将是:

def rule(f):
    f.rule = True
    return f

class RuleType(type):
    def __init__(self, name, bases, attrs):
        self.rules = {}
        for attr, value in attrs.iteritems():
            if getattr(value, 'rule', False):
                self.rules[attr] = value
        super(RuleType, self).__init__(name, bases, attrs)

class RuleBase(object):
    __metaclass__ = RuleType

class RuleClass(RuleBase):
    @rule
    def foo(self):
        pass
Run Code Online (Sandbox Code Playgroud)

请注意,这些都不符合您的要求(修改调用命名空间),因为它很脆弱,很难并且通常是不可能的.相反,它们都__init__通过检查所有属性并填充rules属性来对类进行后处理 - 通过类装饰器或元类的方法.两者之间的区别在于元类解决方案在Python 2.5及更早版本(低至2.2)中工作,并且元类是继承的.使用装饰器,子类必须各自单独应用装饰器(如果他们想要设置rules属性.)

两种解决方案都不考虑继承 - 它们在查找标记为规则的方法时不查看父类,也不查看父类rules属性.如果那是你想要的,那么要扩展它们并不难.