我有以下课程。

Validator是一个修饰器,它接收一个类,该类定义了修饰函数的验证条件。 ValidateKeys是此示例的验证标准。 Node2D是使用验证条件的类。

class Validator(object):
    def __init__(self, TheValidator, *args, **kwargs):
        self.validator = TheValidator(*args,**kwargs)
    def __call__(self,f):
        def wrapped_f(instance, *args,**kwargs):
            self.TheValidator(instance, *args, **kwargs)
            return f(instance,*args,**kwargs)
        return wrapped_f

class ValidateKeys(object):
    def __init__(self,*keysIterable):
        self.validkeys = keysIterable
    def __call__(self, instance, **kwargs):
        for a in kwargs:
            if not a in self.validkeys:
                raise Exception()
        instance.__dict__.update(kwargs)

class Node2D(object):
    @property
    def coords(self):
        return self.__dict__
    @coords.setter
    def coords(self,Coords):
        self.set_coords(**Coords)
    @Validator(ValidateKeys, 'x','y')
    def set_coords(self,**Coords):
        pass


据我了解,在此处编写的内容中,每个Node2D实例都会产生一个重复的Validator(其他装饰有Validator的类也会)和ValidateKeys

编辑:THIS IS WRONG!请参阅下面的答案。

请注意,这主要是我的学习活动,尽管我希望听到批评或建议以改善我的整体方法,但我的主要目标是学习更多有关如何有效使用装饰器的知识。

还要注意,我通常不会在装饰器类中使用大写字母,而是在此处使用大写字母,因为这样可以更容易阅读SO。

最佳答案

我的假设是不正确的。

在编写过程时,每个类仅创建ValidatorValidateKeys的一个实例。我没有意识到@Validator(ValidateKeys, 'x','y')行只运行一次(在类定义时),而在实例创建时没有运行。

我应该意识到这一点,因为装饰器表达式与class attributes处于相同的层次结构级别,例如:

class MyClass():
    class_attribute = None #only one class_attribute is created
    @decorator             #only one decorator (i.e., decorated method) is created
    def method():
        pass


测试:

class Validator(object):
    def __init__(self, TheValidator, *args, **kwargs):
        print("New Validator Object")
        self.TheValidator = TheValidator(*args,**kwargs)
    def __call__(self,f):
        def wrapped_f(instance, *args,**kwargs):
            self.TheValidator(instance, *args, **kwargs)
            return f(instance,*args,**kwargs)
        return wrapped_f

class ValidateKeys(object):
    def __init__(self,*keysIterable):
        print("New ValidateKeys Object")
        self.validkeys = keysIterable
    def __call__(self, instance, **kwargs):
        for a in kwargs:
            if not a in self.validkeys:
                raise Exception()
        instance.__dict__.update(kwargs)

class Node2D(object):
    @property
    def coords(self):
        return self.__dict__
    @coords.setter
    def coords(self,Coords):
        self.set_coords(**Coords)
    @Validator(ValidateKeys, 'x','y')
    def set_coords(self,**Coords):
        pass

n1 = Node2D()
n2 = Node2D()
n1.setcoords(x=1,y=2)
n1.coords


输出:

'New Validator Object'    #<-- Seen only once when module is loaded (class defined)
'New ValidateKeys Object' #<-- Seen only once when module is loaded (class defined)
'{'x': 1, 'y': 2}'


我没有我认为的问题。感谢所有人的帮助。

关于python - 使用装饰器作为类属性而不是实例属性,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/26653422/

10-11 08:33