简体   繁体   English

zope.interface可以定义类'__init__方法应该如何看?

[英]Can zope.interface define how a class' __init__ method should look?

I have several similar classes which will all be initialised by the same code, and thus need to have the same "constructor signature." 我有几个类似的类,它们都将由相同的代码初始化,因此需要具有相同的“构造函数签名”。 (Are there really constructors and signatures in the dynamic Python? I digress.) (在动态Python中是否真的有构造函数和签名?我离题了。)

What is the best way to define a classes __ init __ parameters using zope.interface? 使用zope.interface定义类__init __参数的最佳方法是什么?

I'll paste some code I've used for experimenting with zope.interface to facilitate discussion: 我将粘贴一些我用于试验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)

I can't just define an __ init __ function in ITest, because it will be treated specially by the Python interpreter - I think? 我不能只在ITest中定义一个__ init __函数,因为它将由Python解释器专门处理 - 我想? Whatever the case, it doesn't seem to work. 无论如何,它似乎都不起作用。 So again, what is the best way to define a "class constructor" using a zope.interface? 那么,使用zope.interface定义“类构造函数”的最佳方法是什么?

First of all: there is a big difference between the concepts of providing and implementing an interface. 首先: 提供实现接口的概念之间存在很大差异。

Basically, classes implement an interface, instances of those classes provide that interface. 基本上,类实现了一个接口,这些类的实例提供了该接口。 After all, classes are the blueprints for instances, detailing their implementations. 毕竟,类是实例的蓝图,详细说明了它们的实现。

Now, an interface describes the implementation provided by instances, but the __init__ method is not a part of instances! 现在,接口描述了实例提供的实现,但__init__方法不是实例的一部分! It is part of the interface directly provided by classes instead (a classmethod in Python terminology). 它是由类直接提供的接口的一部分(Python术语中的类方法)。 If you were to define an __init__ method in your interface, you are declaring that your instances have ( provide ) a __init__ method as well (as an instance method). 如果你要定义一个__init__界面中的任何方法,你宣布你的实例都( 提供 )一个__init__方法,以及 (作为一个实例方法)。

So interfaces describe what kind of instances you get, not how you get them. 所以接口描述了你得到的实例,而不是你如何得到它们。

Now, interfaces can be used for more than just describing what functionality an instance provides. 现在,接口不仅可用于描述实例提供的功能。 You can also use interfaces for any kind object in Python, including modules and classes. 您还可以在Python中使用任何类型对象的接口,包括模块和类。 You'll have to use the directlyProvides method to assign an interface to these, as you won't be calling these to create an instance. 您必须使用directlyProvides方法为这些方法分配接口,因为您不会调用它们来创建实例。 You can also use the @provider() class decorator, or the classProvides or moduleProvides functions from within a class or module declaration to get the same results. 您还可以在类或模块声明中使用@provider()类装饰器或classProvidesmoduleProvides函数来获得相同的结果。

What you want in this case is a factory definition; 在这种情况下,您想要的是工厂定义; classes are factories that when called, produce an instance, so a factory interface must provide a __call__ method to indicate they are callable. 类是工厂,当被调用时,生成一个实例,因此工厂接口必须提供__call__方法来指示它们是可调用的。 Here is your example set up with a factory interface: 以下是使用工厂界面设置的示例:

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

The zope.component package provides you with a convenience class and interface for factories , adding a getInterfaces method and a title and description to make discovery and introspection a little easier. zope.component为工厂提供了一个便利类和接口 ,添加了一个getInterfaces方法和一个标题和描述,使发现和内省更容易一些。 You can then just subclass the IFactory interface to document your __init__ parameters a little better: 然后,您可以将IFactory接口子类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)

You could now register that factory as a zope.component utility, for example, allowing other code to find all ITestFactory providers. 您现在可以将该工厂注册为zope.component实用程序,例如,允许其他代码查找所有ITestFactory提供程序。

I used zope.interface.directlyProvides here to mark the factory instance with your subclassed ITestFactory interface, as zope.component.Factory instances normally only provide the IFactory interface. 我在这里使用zope.interface.directlyProvides来标记带有子类ITestFactory接口的工厂实例,因为zope.component.Factory实例通常只提供IFactory接口。

No, __init__ is not handled differently: 不, __init__的处理方式不同:

from zope.interface import Interface, Attribute, implements, verify

class ITest(Interface):
    required_attribute = Attribute(
        """A required attribute for classes implementing this interface.""")
    def __init__(a,b):
        """Takes two parameters"""
    def required_method():
        """A required method for classes implementing this interface."""

class Test(object):
    implements(ITest)
    def __init__(self, a, b):
        self.required_attribute = a*b
    def required_method():
        return self.required_attribute

print verify.verifyClass(ITest, Test)
print verify.verifyObject(ITest, Test(2,3))

I'm not 100% sure what you are asking though. 我不是100%肯定你在问什么。 If you want to have the same constructor signature on several classes in Python, the only way to do that is to actually have the same constructor signature on these classes. 如果你想在Python中的几个类上使用相同的构造函数签名,唯一的方法是在这些类上实际具有相同的构造函数签名。 :-) If you do this by subclassing or by having different __init__ for each class doesn't matter as long as they have the same signature. :-)如果你通过子类化或通过为每个类具有不同的__init__来执行此操作并不重要,只要它们具有相同的签名即可。

zope.interface is not about defining methods, but declaring signatures. zope.interface不是关于定义方法,而是声明签名。 You can therefore define an interface that has a specific signature, also on the __init__ , but this is just saying "This object implements the signature IMyFace", but saying that a class implements an interface will not actually make the class implement the interface. 因此,您可以在__init__上定义具有特定签名的接口,但这只是说“此对象实现了签名IMyFace”,但是说类实现接口实际上不会使类实现接口。 You still need to implement it. 你仍然需要实现它。

Does not make much sense what you are asking. 你问的是没有多大意义。 The interface file is supposed to keep the interface description but not any specific implementation to be called from some where at any point. 接口文件应该保留接口描述,但不能在任何时候从某些地方调用任何特定的实现。 What you what is to inherit. 你要做什么才能继承。 from a common base class. 来自一个共同的基类。 zope.interface is NOT about inheritance. zope.interface不是关于继承。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM