Python 如何将动态数据传递给装饰器
我正在尝试编写一个基本crud控制器类,它执行 以下:Python 如何将动态数据传递给装饰器,python,decorator,Python,Decorator,我正在尝试编写一个基本crud控制器类,它执行 以下: class BaseCrudController: model = "" field_validation = {} template_dir = "" @expose(self.template_dir) def new(self, *args, **kwargs) .... @validate(self.field_validation, error_handler=n
class BaseCrudController:
model = ""
field_validation = {}
template_dir = ""
@expose(self.template_dir)
def new(self, *args, **kwargs)
....
@validate(self.field_validation, error_handler=new)
@expose()
def post(self, *args, **kwargs):
...
我的目的是让我的控制器扩展这个基类,设置
模型、现场验证和模板位置,我已准备就绪
不幸的是,装饰师(据我所知)在
定义了该函数。因此,它将无法访问实例的
价值是否有方法从子系统传入动态数据或值
上课
例如:
class AddressController(BaseCrudController):
model = Address
template_dir = "addressbook.templates.addresses"
import functools
def expose(attname=None):
if attname:
def makewrapper(f):
@functools.wraps(f)
def wrapper(self, *a, **k):
attvalue = getattr(self, attname, None)
...use attvalue as needed...
return wrapper
return makewrapper
else:
...same but without the getattr...
当我尝试加载AddressController时,它说“未定义self”。我假设基类在初始化子类之前正在评估decorator
谢谢,
Steve使用工厂创建类可能比子类化更好:
def CrudControllerFactory(model, field_validation, template_dir):
class BaseCrudController:
@expose(template_dir)
def new(self, *args, **kwargs)
....
@validate(field_validation, error_handler=new)
@expose()
def post(self, *args, **kwargs):
....
return BaseCrudController
不幸的是,装饰师(对我来说)
理解),当
定义了该函数。因此
无法访问实例的值。
有没有办法传入动态数据
或者来自子类的值
需要使用相关属性的名称调用模板;然后包装器可以动态地获取该属性的值。例如:
class AddressController(BaseCrudController):
model = Address
template_dir = "addressbook.templates.addresses"
import functools
def expose(attname=None):
if attname:
def makewrapper(f):
@functools.wraps(f)
def wrapper(self, *a, **k):
attvalue = getattr(self, attname, None)
...use attvalue as needed...
return wrapper
return makewrapper
else:
...same but without the getattr...
请注意,复杂的原因只是,从Q中的代码片段判断,您希望允许expose
装饰器与参数一起使用,也可以不使用参数(如果attname保护在包装中,您可以移动,但是在每次调用时重复检查是无用的——我想,在这两种情况下,包装中的代码可能也需要非常不同——因此,将两个不同的控制流塞入一个包装中可能会更加复杂)顺便说一句,这是一个可疑的设计决策,IMHO。但是,它与您关于“动态数据”的实际Q完全不同
关键是,通过使用属性名作为参数,您可以授权装饰程序在需要时“及时”动态获取值。可以将其视为“额外的间接层次”,这是解决编程中所有困难的广为人知的灵丹妙药!-)有趣的想法。但这不会限制我扩展实际控制器的能力吗?我希望基本控制器能帮助我处理所有crud情况,并允许我向扩展基类的控制器添加功能。您必须像class ExtendedClass(CrudControllerFactor(model,field\u validation,template\u dir)这样创建子类:
。如果希望对子类进行子类化,则可能会出现问题。只要在同一个文件中定义了值,我就可以设置该值:template\u dir=“address”@expose(template\u dir),但当我尝试这样做时:@expose(self.template\u dir)然后在子类中定义self.template\u dir,它说self未定义。我用一个例子编辑了我的Q。@steve,当然了:在模板执行时没有self
。正如我所解释的,通过传递属性名,你可以获得额外的间接级别,并完全解决问题。我想我现在就得到了这个。所以我会我必须编写另一个@expose来覆盖现有的一个。调用@expose(attrname=“template_dir”),并编写一个包装器来计算template_dir的值?@steve,是的,大致上是这样,但是要小心在同一命名空间中有几个同名的对象:你不能!Python不支持C++之类的“重载”(不同的函数具有相同的名称,根据其类型和参数数量进行区分)。您可能希望为不同的功能使用不同的名称(这比将许多不同的功能塞进一个函数中要清楚得多)。