gpt4 book ai didi

python - 装饰器调用实例方法

转载 作者:行者123 更新时间:2023-12-01 04:52:38 24 4
gpt4 key购买 nike

我有一个类 A ,其方法为 do_something(self,a,b,c) 和另一个验证输入并检查名为 can_do_something 的权限的实例方法(自身,a,b,c)

这是我的代码中的常见模式,我想编写一个接受验证函数名称并执行测试的装饰器。

def validate_input(validation_fn_name):
def validation_decorator(func):
def validate_input_action(self,*args):
error = getattr(self,validation_fn_name)(*args)
if not error == True:
raise error
else:
return func(*args)
return validate_input_action
return validation_decorator

调用函数如下

@validate_input('can_do_something')
def do_something(self,a,b,c):
return a + b + c

问题是我不确定如何在验证函数中维护self。我已将验证 fn 名称与 getattr 一起使用,因此 fn 可以在实例的上下文中运行,但我无法对 func(*args) 执行此操作。

那么实现这一目标的正确方法是什么?

谢谢。

编辑

因此,在 @André Laszlo 回答之后,我意识到 self 只是第一个参数,因此根本不需要使用 getattr,只需传递 *args 即可。

def validate_input(validation_fn):
def validation_decorator(func):
def validate_input_action(*args):
error = validation_fn(*args)
if not error == True:
raise error
else:
return func(*args)
return validate_input_action
return validation_decorator

更加优雅,它还支持静态方法。

向 @André Laszlo 示例添加静态方法证明装饰器正在工作:

 class Foo(object):
@staticmethod
def validate_baz(a,b,c):
if a > b:
return ValueError('a gt b')

@staticmethod
@validate_input(Foo.validate_baz)
def baz(a,b,c):
print a,b,c

>>> Foo.baz(1,2,3)
1 2 3
>>> Foo.baz(2,1,3)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 6, in validate_input_action
ValueError: a gt b

但是,当我尝试在 django 模型中做同样的事情时:

from django.db import models
from django.conf import settings

settings.configure()

class Dummy(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=10)

def can_say_name(self):
if name is None:
return Exception('Does not have a name')

@validate_input(can_say_name)
def say_name(self):
print self.name

@staticmethod
def can_create_dummy(name):
if name == 'noname':
return Exception('No name is not a name !')

@staticmethod
@validate_input(Dummy.can_create_dummy)
def create_dummy(name):
return Dummy.objects.create(name=name)

我得到以下信息:

NameError: name 'Dummy' is not defined

那么在这个问题上,django 模型和对象有什么不同呢?

最佳答案

我认为这符合你的要求:

def validate_input(validation_fn_name):
def validation_decorator(func):
def validate_input_action(self, *args):
error = getattr(self, validation_fn_name)(*args)
if error is not None:
raise error
else:
arglist = [self] + list(args)
return func(*arglist)
return validate_input_action
return validation_decorator

class Foo(object):

def validate_length(self, arg1):
if len(arg1) < 3:
return ValueError('%r is too short' % arg1)

@validate_input('validate_length')
def bar(self, arg1):
print "Arg1 is %r" % arg1


if __name__ == "__main__":
f = Foo()
f.bar('hello')
f.bar('')

输出是:

Arg1 is 'hello'
Traceback (most recent call last):
File "validator.py", line 27, in <module>
f.bar('')
File "validator.py", line 6, in validate_input_action
raise error
ValueError: '' is too short

更新答案

发生错误(NameError: name 'Dummy' is not Defined)是因为在 validate_input 装饰器时尚未定义 Dummy 类获取 Dummy 作为参数。我想这可以用不同的方式实现,但现在这就是 Python 的工作方式。我看到的最简单的解决方案是坚持使用 getattr,它会起作用,因为它在运行时查找方法。

关于python - 装饰器调用实例方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28085694/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com