<p>问题是<code>apply_validation</code>是一个方法,这意味着您需要在<code>ValidatedObject</code>的实例上调用它。不幸的是,在调用它时(在<code>test</code>类的定义期间),没有合适的实例可用。你需要一个不同的方法。你知道吗</p>
<p>最明显的一种方法是使用一个元类来搜索它的实例字典(实际上是类字典),并根据找到的内容设置<code>_validations</code>变量。您仍然可以使用decorator,但它可能应该是一个全局函数,或者可能是一个静态方法,并且需要以不同的方式工作。下面是一些使用元类和添加函数属性的装饰器的代码:</p>
<pre><code>class ValidatedMeta(type):
def __new__(meta, name, bases, dct):
validations = [Validation(f._validation_field_name, f._validation_code, f)
for f in dct.values if hasattr(f._validation_field_name)]
dct["_validations"] = validations
super(ValidatedMeta, meta).__new__(meta, name, bases, dct)
def apply_validation(field_name, code):
def decorator(f):
f._validation_field_name = field_name
f._validation_code = code
return f
return decorator
def ValidatedObject(metaclass=ValidatedMeta):
pass
class test(ValidatedObject):
@apply_validation("_name", "oh no!")
def name_validation(self, name):
return name == "jacob"
</code></pre>
<p>此代码运行后,<code>test._validations</code>将是<code>[Validation("_name", "oh no!", test.name_validation)]</code>。请注意,传递给<code>Validation</code>的方法是未绑定的,因此您需要在调用它时自己传递一个<code>self</code>参数(或者删除<code>self</code>参数并将在<code>apply_validation</code>中创建的装饰器更改为返回<code>staticmethod(f)</code>)。你知道吗</p>
<p>如果在继承层次结构的多个级别上定义了验证方法,则此代码可能无法实现所需的功能。上面所写的元类只检查立即类的dict中是否有具有适当属性的方法。如果需要在<code>_validations</code>中也包含继承的方法,则可能需要修改<code>ValidatedMeta.__new__</code>中的逻辑。可能最简单的方法是在<code>bases</code>中查找<code>_validations</code>属性并将列表连接在一起。你知道吗</p>