python装饰器修改当前范围内的变量

标签 python scope decorator

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

如果有效:

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

    def one(self):
        pass

    @decorated
    def two(self):
        pass

>>> Blah.decorated
["two"]

为什么?我基本上想编写可以维护特定方法字典的类,以便我可以在每个类的基础上检索不同类型的可用方法列表。错了……

我想这样做:

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"]

最佳答案

您可以使用类装饰器(在 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

元类版本为:

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

请注意,这两种方法都不能满足您的要求(修改调用命名空间),因为它脆弱、困难且通常是不可能的。相反,它们都通过类装饰器或元类的 __init__ 方法对类进行后处理,方法是检查所有属性并填充 rules 属性。两者的区别在于,元类解决方案适用于 Python 2.5 及更早版本(降至 2.2),并且元类是继承的。使用装饰器,子类必须分别应用装饰器(如果它们想设置规则属性。)

这两种解决方案都没有考虑继承——它们在查找标记为规则的方法时不查看父类,也不查看父类的 rules 属性。如果这是您想要的,那么扩展两者都不难。

关于python装饰器修改当前范围内的变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2714244/

相关文章:

python - 装饰设计: executing a method only if it has been overridden

python - 我将什么类型的数据传递到 Django Model.save() 方法中?

PHP OOP MySQL (WAMP) 变量作用域

java - 从另一个 JSP 文件读取变量

c# - 如何在C#中自动生成装饰器模式

Python类装饰器

python - 无法找到带有 Selenium 的文本元素

python - 与导入的模块共享调用者的命名空间

python - 使用 pyodbc 时为 "CREATE ... statement not allowed within multi-statement transaction"

IEnumerable<T> 的 C# 匿名方法变量范围问题