我有以下课程。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。
最佳答案
我的假设是不正确的。
在编写过程时,每个类仅创建Validator
和ValidateKeys
的一个实例。我没有意识到@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/