Question

J'ai commencé à utiliser des interfaces Zope dans mon code, et que maintenant, ils sont vraiment à notre documentation. Je les utilise pour spécifier les attributs de la classe doit posséder, les mettre en œuvre explicitement dans les classes appropriées et vérifier explicitement pour eux où j'attends un. Cela est bien, mais je les aime faire plus, si possible, par exemple vérifier effectivement que la classe a mis en oeuvre l'interface, au lieu de simplement vérifier que je l'ai dit que la classe implémente l'interface. J'ai lu le wiki Zope deux ou trois fois, mais ne peut toujours pas voir l'utilisation beaucoup plus pour les interfaces que ce que je fais actuellement. Alors, ma question est que pouvez-vous utiliser ces interfaces pour les autres, et comment les utilisez-vous pour plus.

Était-ce utile?

La solution

Vous pouvez réellement tester si votre objet ou la classe implémente l'interface. Pour cela, vous pouvez utiliser le module de verify (vous le feriez normalement utiliser dans vos tests):

>>> from zope.interface import Interface, Attribute, implements
>>> class IFoo(Interface):
...     x = Attribute("The X attribute")
...     y = Attribute("The Y attribute")

>>> class Foo(object):
...     implements(IFoo)
...     x = 1
...     def __init__(self):
...         self.y = 2

>>> from zope.interface.verify import verifyObject
>>> verifyObject(IFoo, Foo())
True

>>> from zope.interface.verify import verifyClass
>>> verifyClass(IFoo, Foo)
True

Les interfaces peuvent également être utilisés pour le réglage et le test invariants. Vous trouverez plus d'informations ici:

http://www.muthukadan.net/docs/zca.html#interfaces

Autres conseils

Là où je travaille, nous utilisons des interfaces pour que nous puissions utiliser ZCA ou Zope Component Architecture , qui est un cadre entier pour la fabrication de composants qui sont permutables et Pluggable utilisant Interfaces. Nous utilisons ZCA pour que nous puissions faire face à toutes sortes de par client customisations sans nécessairement avoir à fourche notre logiciel ou ont tous les nombreux bits par client salissant l'arbre principal. Le wiki Zope est souvent très incomplète, malheureusement. Il y a une bonne mais laconique-explication de la plupart des fonctionnalités de ZCA sur son page pypi de ZCA .

Je n'utilise Interfaces quoi que ce soit comme vérifier qu'une classe implémente toutes les méthodes pour un Interface donné. En théorie, cela pourrait être utile lorsque vous ajoutez une autre méthode à une interface, pour vérifier que vous avez pensé à ajouter la nouvelle méthode pour toutes les classes qui mettent en œuvre l'interface. Personnellement, je préfère fortement de créer un nouveau Interface sur la modification d'un ancien. Modification ancienne Interfaces est généralement une très mauvaise idée une fois qu'ils sont dans les œufs qui ont été libérés à PyPI ou au reste de votre organisation.

Une note rapide sur la terminologie: les classes outil Interfaces et objets (instances de classes) fournir Interfaces. Si vous voulez vérifier un Interface, vous soit écrire ISomething.implementedBy(SomeClass) ou ISomething.providedBy(some_object).

Alors, jusqu'à des exemples où ZCA est utile. Feignons que nous écrivons un blog, en utilisant la ZCA pour le rendre modulaire. Nous aurons un objet BlogPost pour chaque poste, qui fournira une interface IBlogPost, tous définis dans notre oeuf my.blog pratique dandy. Nous allons également enregistrer la configuration du blog dans les objets BlogConfiguration qui fournissent IBlogConfiguration. En utilisant comme point de départ, nous pouvons mettre en œuvre de nouvelles fonctionnalités sans nécessairement avoir à toucher my.blog du tout.

Ce qui suit est une liste d'exemples de choses que nous pouvons faire en utilisant ZCA, sans avoir à modifier l'œuf base my.blog. I ou mes collègues ont fait toutes ces choses (et les ont trouvées utiles) sur des projets concrets pour le client, mais nous ne les blogs en œuvre à l'époque. :) Certains des cas d'utilisation ici pourraient être mieux résolus par d'autres moyens, par exemple un fichier CSS d'impression.

  1. Ajout de vues supplémentaires (BrowserViews, généralement enregistrés dans ZCML avec la directive browser:page) à tous les objets qui fournissent IBlogPost. Je pourrais faire un oeuf my.blog.printable. Cet œuf enregistrerait un BrowserView appelé print pour IBlogPost, ce qui rend le billet de blog par un Zope page Template conçu pour produire du HTML qui imprime bien. Ce BrowserView alors apparaître à l'/path/to/blogpost/@@print URL.

  2. Le mécanisme de souscription d'événement dans Zope. Disons que je veux publier flux RSS, et je veux les générer à l'avance plutôt que sur demande. Je pourrais créer un oeuf my.blog.rss. Dans cet œuf, j'inscrire un abonné pour les événements qui fournissent IObjectModified (zope.lifecycleevent.interfaces.IObjectModified), sur des objets qui fournissent IBlogPost. Ce serait abonné se faire appelé à chaque fois qu'un attribut a changé quoi que ce soit sur la fourniture IBlogPost, et je pourrais l'utiliser pour mettre à jour tous les flux RSS que le billet de blog devrait apparaître.

    Dans ce cas, il pourrait être préférable d'avoir un événement IBlogPostModified qui est envoyé à la fin de chacun des BrowserViews qui modifient les messages de blog, depuis IObjectModified se sent une fois sur chaque changement d'attribut unique -. qui pourrait être trop souvent à cause de la performance

  3. Adaptateurs

    . Les adaptateurs sont effectivement « moulages » d'une interface à l'autre. Pour les geeks de langage de programmation: adaptateurs Zope mettre en œuvre « ouvert » multiples expédition en Python (par « ouvert » je veux dire «vous pouvez ajouter plus de cas de tout œuf »), avec une interface plus spécifiques de matchs en priorité sur les matchs moins spécifiques (Interface Les classes peuvent être sous-classes les uns des autres, et cela fait exactement ce que vous espérons qu'il le ferait.)

    adaptateurs d'un Interface peuvent être appelées avec une syntaxe très agréable, ISomething(object_to_adapt), ou peuvent être obtenues via la fonction zope.component.getAdapter. Adaptateurs de plusieurs Interfaces doivent être obtenues via la fonction zope.component.getMultiAdapter, ce qui est un peu moins jolie.

    Vous pouvez avoir plus d'un adaptateur pour un ensemble donné de Interfaces, différenciés par un name de chaîne que vous fournissez lors de l'enregistrement de l'adaptateur. Par défaut, le nom de "". Par exemple, BrowserViews sont en fait des adaptateurs qui s'adaptent de l'interface qu'ils sont enregistrés sur une interface et que les outils de la classe HTTPRequête. Vous pouvez également rechercher des paires tous des adaptateurs qui sont enregistrés d'une séquence de Interfaces à un autre Interface, en utilisant zope.component.getAdapters( (IAdaptFrom,), IAdaptTo ), qui retourne une séquence de (nom, adaptateur). Ceci peut être utilisé comme un moyen très agréable de fournir des crochets pour les plugins pour se joindre à.

    Dire que je voulais sauver tous les messages de mon blog et la configuration comme un grand fichier XML. Créer un œuf de my.blog.xmldump qui définit un IXMLSegment, et enregistre un adaptateur de IBlogPost à IXMLSegment et un adaptateur de IBlogConfiguration à IXMLSegment. Je peux maintenant appeler selon adaptateur est approprié pour un objet que je veux sérialisation en écrivant IXMLSegment(object_to_serialize).

    Je pourrais même ajouter plusieurs adaptateurs de diverses autres choses à IXMLSegment d'oeufs autres que my.blog.xmldump. ZCML dispose d'une fonction où il peut exécuter une directive particulière si et seulement si un œuf est installé. Je pourrais l'utiliser pour avoir my.blog.rss enregistrer un adaptateur de IRSSFeed à IXMLSegment ssi my.blog.xmldump arrive à installer, sans faire dépendre my.blog.rss my.blog.xmldump.

  4. Viewlets sont comme des petits BrowserViews que vous pouvez avoir « subscribe » à un endroit particulier à l'intérieur d'une page. Je ne me souviens pas de tous les détails en ce moment, mais ceux-ci sont très bonnes pour des choses comme les plugins que vous souhaitez voir apparaître dans une barre latérale.

    Je ne me souviens pas si désinvolture qu'ils font partie de la base Zope ou Plone. Je recommande de ne pas utiliser à moins que le problème Plone que vous essayez de résoudre réellement besoin d'un véritable CMS, car il est un grand et complexe logiciel et il a tendance à être un peu lent.

    Vous n'êtes pas nécessairement réellement besoin Viewlets de toute façon, puisque BrowserViews peuvent appeler les uns les autres, que ce soit en utilisant « objet / @@ some_browser_view » dans une expression TAL, ou en utilisant queryMultiAdapter( (ISomething, IHttpRequest), name='some_browser_view' ), mais ils sont assez agréable quel que soit.

  5. Interfaces de marqueur. Un Interface marqueur est un Interface qui fournit aucune méthode et aucun attribut. Vous pouvez ajouter un marqueur Interface tout objet à l'exécution en utilisant ISomething.alsoProvidedBy. Cela vous permet, par exemple, modifier les adaptateurs se habituera sur un objet particulier et qui BrowserViews seront définies là-dessus.

Je suis désolé que je ne suis pas allé dans suffisamment de détails pour être en mesure de mettre en œuvre directement chacun de ces exemples là, mais ils prendraient environ un billet de blog chacun.

interfaces Zope peuvent fournir un moyen utile pour découpler deux morceaux de code qui ne devrait pas dépendre les uns des autres.

Disons que nous avons un composant qui sait comment imprimer un message d'accueil dans le module a.py:

>>> class Greeter(object):
...     def greet(self):
...         print 'Hello'

Et un code qui a besoin d'imprimer un message d'accueil dans le module b.py:

>>> Greeter().greet()
'Hello'

Cet arrangement rend difficile d'échanger le code qui gère le message d'accueil sans toucher b.py (qui pourrait être distribué dans un emballage séparé). Au lieu de cela, nous pourrions introduire un troisième module c.py qui définit une interface IGreeter:

>>> from zope.interface import Interface
>>> class IGreeter(Interface):
...     def greet():
...         """ Gives a greeting. """

Maintenant, nous pouvons l'utiliser pour découpler a.py et b.py. Au lieu d'instancier une classe Greeter, b.py va maintenant demander un utilitaire fournissant l'interface IGreeter. Et a.py déclarera que la classe Greeter implémente cette interface:

(a.py)
>>> from zope.interface import implementer
>>> from zope.component import provideUtility
>>> from c import IGreeter

>>> @implementer(IGreeter)
... class Greeter(object):
...     def greet(self):
...         print 'Hello'
>>> provideUtility(Greeter(), IGreeter)

(b.py)
>>> from zope.component import getUtility
>>> from c import IGreeter

>>> greeter = getUtility(IGreeter)
>>> greeter.greet()
'Hello'

Je ne l'ai jamais utilisé les interfaces Zope, mais vous pourriez envisager d'écrire un de métaclasse, qui lors de l'initialisation vérifie les membres de la classe à l'encontre de l'interface, et soulève une exception d'exécution si une méthode ne soit pas mise en oeuvre.

Avec Python vous n'avez pas d'autres options. Soit ont une étape « compilation » qui inspecte votre code, ou inspectent dynamiquement lors de l'exécution.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top