我有以下课程。
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
装饰的任何其他类一样)和{{1} }。
编辑:THIS IS WRONG!请参阅下面的答案。
请注意,这主要是我的学习练习,虽然我有兴趣听取批评/建议以改进我的所有方法,但我的主要目标是了解如何有效地使用装饰器。
另请注意,我通常不会对装饰器类使用大写,但我在此处使用它,因为它使得在SO上更容易阅读。
答案 0 :(得分:2)
我的假设不正确。
编写内容时,每个类只创建一个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}'
我没有遇到过我认为的问题。感谢大家的帮助。