我需要为界面中的每个属性添加一个属性。所以我试图动态地修改它来添加它们,但现在还没有取得多大成功。
假设我有以下界面:
class IMember(Interface):
first_name = schema.TextLine(title=u'first name')
last_name = schema.TextLine(title=u'last name')
我想修改它:
class IMember(Interface):
first_name = schema.TextLine(title=u'first name')
last_name = schema.TextLine(title=u'last name')
visbility_first_name = schema.Bool(title=u'Display: first name')
visbility_last_name = schema.Bool(title=u'Display: last name')
我之后尝试修改了类,但由于它已经初始化,因此设置了架构,我不知道如何更改它。我还考虑过写一个指令(例如:interface.Implements()),但添加属性似乎很复杂。
我的最终目标是添加一个带有一组Bool小部件的z3c.form字段集。
那么,有没有办法在Python中完成,或者我是否必须修改界面并手动添加所有属性?
谢谢!
答案 0 :(得分:6)
您可以使用InterfaceClass
元类型创建接口的动态子类。
创建其他架构字段的字典:
fields = {}
for name, attr in IMember.namesAndDescriptions():
if isinstance(attr, schema.Field):
fields['visible_' + name] = schema.Bool(title=u'Display: ' + attr.title)
现在,您可以创建一个动态接口,为现有界面创建子类:
from zope.interface.interface import InterfaceClass
IMemberExtended = InterfaceClass('IMemberExtended', (IMember,), fields)
如果您愿意,这可以全部包含在类装饰器中:
from zope.interface.interface import InterfaceClass
from zope import schema
def add_visibility_fields(iface):
fields = {}
for name, attr in iface.namesAndDescriptions():
if isinstance(attr, schema.Field):
fields['visible_' + name] = schema.Bool(title=u'Display: ' + attr.title)
return InterfaceClass(iface.__name__, (iface,), fields)
您在现有界面上使用的:
@add_visibility_fields
class IMember(Interface):
first_name = schema.TextLine(title=u'first name')
last_name = schema.TextLine(title=u'last name')
这会创建一个子类;您还可以使用生成的界面替换整个界面:
def add_visibility_fields(iface):
fields = {}
for name, attr in iface.namesAndDescriptions():
fields[name] = attr
if isinstance(attr, schema.Field):
fields['visible_' + name] = schema.Bool(title=u'Display: ' + attr.title)
return InterfaceClass(iface.__name__, iface.__bases__, fields)
最后一个版本的演示:
>>> @add_visibility_fields
... class IMember(Interface):
... first_name = schema.TextLine(title=u'first name')
... last_name = schema.TextLine(title=u'last name')
...
>>> IMember.names()
['visible_last_name', 'first_name', 'last_name', 'visible_first_name']
答案 1 :(得分:0)
好像你想使用python的元类。使用自定义元类将允许您修改类的创建,因此您可以在创建类之前/之前动态添加或修改属性。有关元类的优秀SO答案,请参阅this post。
但是,您应该尝试重新构建程序以避免使用元类。通常情况下,如果您确实知道自己需要它们,则应仅使用它们。在你的情况下,是否可以修改schema.TextLine
以允许你想要的行为(可能通过添加一个钩子)?