zope.interface 可以定义类如何定义吗? __init__ 方法应该是什么样子?

发布于 2024-10-23 20:09:18 字数 820 浏览 1 评论 0原文

我有几个类似的类,它们都将由相同的代码初始化,因此需要具有相同的“构造函数签名”。 (动态 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)

我不能只在 ITest 中定义 __ init __ 函数,因为它会被 Python 解释器特殊对待 - 我想?不管怎样,它似乎不起作用。那么,使用 zope.interface 定义“类构造函数”的最佳方法是什么?

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.)

What is the best way to define a classes __ init __ parameters using zope.interface?

I'll paste some code I've used for experimenting with zope.interface to facilitate discussion:


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? 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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

北笙凉宸 2024-10-30 20:09:18

首先:提供接口和实现接口的概念有很大区别。

基本上,类实现一个接口,这些类的实例提供该接口。毕竟,类是实例的蓝图,详细说明了它们的实现。

现在,接口描述了实例提供的实现,但是 __init__ 方法不是实例的一部分!它是类直接提供的接口的一部分(Python 术语中的类方法)。如果您要在接口中定义 __init__ 方法,则您声明您的实例具有(提供)一个 __init__ 方法为好吧(作为实例方法)。

因此,接口描述了您获得的实例类型,而不是如何获得它们。

现在,接口不仅仅可以用于描述实例提供的功能。您还可以使用 Python 中任何类型对象的接口,包括模块和类。您必须使用directlyProvides方法为它们分配一个接口,因为您不会调用它们来创建实例。您还可以使用类或模块声明中的 @provider() 类装饰器或 classProvidesmoduleProvides 函数来获得相同的结果结果。

在这种情况下你想要的是一个工厂定义;类是工厂,在调用时会生成实例,因此工厂接口必须提供 __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

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)

您现在可以将该工厂注册为 zope.component 实用程序例如,允许其他代码查找所有 ITestFactory 提供程序。

我在这里使用 zope.interface.directlyProvides 来使用子类 ITestFactory 接口来标记工厂实例,因为 zope.component.Factory 实例通常只提供IFactory 接口。

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! It is part of the interface directly provided by classes instead (a classmethod in Python terminology). 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).

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. 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. 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.

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. 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. You can then just subclass the IFactory interface to document your __init__ parameters a little better:

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.

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.

メ斷腸人バ 2024-10-30 20:09:18

不, __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))

但我不能 100% 确定你在问什么。如果您希望 Python 中的多个类具有相同的构造函数签名,唯一的方法就是在这些类上实际上具有相同的构造函数签名。 :-) 如果您通过子类化或为每个类使用不同的 __init__ 来做到这一点,那么只要它们具有相同的签名,就没有关系。

zope.interface 不是定义方法,而是声明签名。因此,您可以定义一个具有特定签名的接口,也在 __init__ 上,但这只是说“这个对象实现了签名 IMyFace”,但说一个类实现了一个接口实际上并不会使类实现接口。你仍然需要实施它。

No, __init__ is not handled differently:

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. 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. :-) 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.

zope.interface is not about defining methods, but declaring signatures. 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. You still need to implement it.

∞梦里开花 2024-10-30 20:09:18

你问的没有多大意义。接口文件应该保留接口描述,但不保留从任何地方调用的任何特定实现。你什么就是继承什么。来自公共基类。 zope.interface 与继承无关。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文