我有几个类似的类,它们都将由相同的代码初始化,因此需要具有相同的"构造函数签名".(在动态Python中是否真的有构造函数和签名?我离题了.)
使用zope.interface定义类__init __参数的最佳方法是什么?
我将粘贴一些我用于试验zope.interface的代码以方便讨论:
from zope.interface import Interface, Attribute, implements, verify
class ITest(Interface):
required_attribute = Attribute(
"""A required attribute for classes implementing this interface.""")
def required_method():
"""A required method for classes implementing this interface."""
class Test(object):
implements(ITest)
required_attribute = None
def required_method():
pass
print verify.verifyObject(ITest, Test())
print verify.verifyClass(ITest, Test)
Run Code Online (Sandbox Code Playgroud)
我不能只在ITest中定义一个__ init __函数,因为它将由Python解释器专门处理 - 我想?无论如何,它似乎都不起作用.那么,使用zope.interface定义"类构造函数"的最佳方法是什么?
首先:提供和实现接口的概念之间存在很大差异.
基本上,类实现了一个接口,这些类的实例提供了该接口.毕竟,类是实例的蓝图,详细说明了它们的实现.
现在,接口描述了实例提供的实现,但该__init__方法不是实例的一部分!它是由类直接提供的接口的一部分(Python术语中的类方法).如果你要定义一个__init__在你的接口方法,你宣布你的实例都(提供)一个__init__方法,以及(作为一个实例方法).
所以接口描述了你得到的实例,而不是你如何得到它们.
现在,接口不仅可用于描述实例提供的功能.您还可以在Python中使用任何类型对象的接口,包括模块和类.您必须使用该directlyProvides方法为这些方法分配接口,因为您不会调用它们来创建实例.您还可以使用@provider()类装饰器或类或模块声明中的classProvides或moduleProvides函数来获得相同的结果.
在这种情况下,您想要的是工厂定义; 类是工厂,当被调用时,生成一个实例,因此工厂接口必须提供一个__call__方法来指示它们是可调用的.以下是使用工厂界面设置的示例:
from zope import interface
class ITest(interface.Interface):
required_attribute = interface.Attribute(
"""A required attribute for classes implementing this interface.""")
def required_method():
"""A required method for classes implementing this interface."""
class ITestFactory(interface.Interface):
"""Creates objects providing the ITest interface"""
def __call__(a, b):
"""Takes two parameters"""
@interface.implementer(ITest)
@interface.provider(ITestFactory)
class Test(object):
def __init__(self, a, b):
self.required_attribute = a*b
def required_method():
return self.required_attribute
Run Code Online (Sandbox Code Playgroud)
该zope.component软件包为工厂提供了便利类和界面,添加了getInterfaces方法,标题和描述,使发现和内省更容易一些.然后,您可以将IFactory接口子类化为__init__更好地记录参数:
from zope import component
class ITestFactory(component.interfaces.IFactory):
"""Creates objects providing the ITest interface"""
def __call__(a, b):
"""Takes two parameters"""
testFactory = component.Factory(Test, 'ITest Factory', ITestFactory.__doc__)
interface.directlyProvides(testFactory, ITestFactory)
Run Code Online (Sandbox Code Playgroud)
您现在可以将该工厂注册为zope.component实用程序,例如,允许其他代码查找所有ITestFactory提供程序.
我zope.interface.directlyProvides在这里用你的子类ITestFactory接口标记工厂实例,因为zope.component.Factory实例通常只提供IFactory接口.