Domanda

Ho iniziato a utilizzare le interfacce di Zope nel mio codice, e fin d'ora, sono in realtà solo la documentazione. Li uso per specificare quali attributi della classe deve possedere, implementarli in modo esplicito nelle classi corrispondenti ed esplicitamente verificare la presenza di loro dove mi aspetto uno. Questo va bene, ma vorrei che facessero più, se possibile, come verificare effettivamente che la classe ha implementato l'interfaccia, invece di verificare che ho detto che la classe implementa l'interfaccia. Ho letto il wiki Zope un paio di volte, ma ancora non riesco a vedere molto di più l'uso di interfacce di quello che sto facendo attualmente. Quindi, la mia domanda è che cosa altro si può utilizzare queste interfacce per, e come si fa a usarli di più.

È stato utile?

Soluzione

Si può effettivamente verificare se il vostro oggetto o classe implementa l'interfaccia. Per questo si può utilizzare il modulo verify (che si usa normalmente nelle vostre test):

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

interfacce possono essere utilizzate anche per l'impostazione e il test invarianti. E 'possibile trovare maggiori informazioni qui:

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

Altri suggerimenti

Dove lavoro, usiamo interfacce in modo da poter usare ZCA, o Zope Component Architecture , che è un quadro intero per realizzare componenti che sono sostituibili e Pluggable usando Interfaces. Usiamo ZCA modo da poter far fronte a tutti i tipi di personalizzazioni per-client senza necessariamente dover spendere nostro software o avere tutti i molti bit per-client rovinare l'albero principale. Il wiki Zope è spesso molto incompleta, purtroppo. C'è una spiegazione buona-but-tersa della maggior parte delle caratteristiche di ZCA sul suo pagina PyPI di ZCA .

Non faccio uso di Interfaces per una cosa del genere la verifica che una classe implementa tutti i metodi per un determinato Interface. In teoria, questo potrebbe essere utile quando si aggiunge un altro metodo per un'interfaccia, per verificare che hai ricordato di aggiungere il nuovo metodo a tutte le classi che implementano l'interfaccia. Personalmente preferisco vivamente di creare una nuova Interface sopra modificando una vecchia. Modifica vecchio Interfaces è di solito una pessima idea una volta che sono in uova che sono stati rilasciati per PyPI o per il resto della vostra organizzazione.

Una breve nota sulla terminologia: classi attuare Interfaces e oggetti (istanze di classi) fornire Interfaces. Se si desidera verificare la presenza di un Interface, si dovrebbe scrivere o ISomething.implementedBy(SomeClass) o ISomething.providedBy(some_object).

Quindi, fino a esempi di dove ZCA è utile. Facciamo finta che stiamo scrivendo un blog, utilizzando lo ZCA per renderlo modulare. Avremo un oggetto BlogPost per ogni post, che fornirà un'interfaccia IBlogPost, tutti definiti nel nostro uovo my.blog comodo-dandy. Ci sarà anche archivio di configurazione del blog negli oggetti BlogConfiguration che forniscono IBlogConfiguration. Usando questo come punto di partenza, siamo in grado di implementare nuove funzionalità senza necessariamente dover toccare my.blog a tutti.

Quello che segue è un elenco di esempi di cose che possiamo fare utilizzando ZCA, senza dover modificare l'uovo di base my.blog. Io oi miei collaboratori ho fatto tutte queste cose (e li ha trovati utili) su progetti reali per-client, anche se non siamo stati implementando i blog al momento. :) Alcuni dei casi d'uso qui potrebbe essere meglio risolti con altri mezzi, come ad esempio un file di stampa CSS.

  1. L'aggiunta di prospettive in eccesso (BrowserViews, in genere registrati negli ZCML con la direttiva browser:page) a tutti gli oggetti che forniscono IBlogPost. Potrei fare un uovo my.blog.printable. Quell'uovo registrerebbe un BrowserView chiamato print per IBlogPost, che rende il post sul blog attraverso un Zope modello di pagina progettato per produrre HTML che consente di stampare bene. Quella BrowserView allora apparirà in /path/to/blogpost/@@print URL.

  2. Il meccanismo di sottoscrizione di eventi in Zope. Dire che voglio pubblicare feed RSS, e voglio generare in anticipo piuttosto che su richiesta. Potrei creare un uovo my.blog.rss. In quell'uovo, mi piacerebbe registrare un abbonato per gli eventi che forniscono IObjectModified (zope.lifecycleevent.interfaces.IObjectModified), su oggetti che forniscono IBlogPost. Quella abbonato otterrebbe sarebbe chiamato ogni volta che un attributo è cambiato su qualsiasi cosa che fornisce IBlogPost, e ho potuto usarlo per aggiornare tutti i feed RSS che il post sul blog dovrebbe apparire in.

    In questo caso, potrebbe essere meglio avere un evento IBlogPostModified che viene inviato alla fine di ciascuno dei BrowserViews che modificano i post del blog, dal momento che IObjectModified ottiene sent una volta su ogni singola modifica attributo -. che potrebbe essere troppo spesso per il bene di prestazioni

  3. Adattatori. Gli adattatori sono effettivamente "getta" da un'interfaccia all'altra. Per i geek Linguaggio di programmazione: adattatori Zope implementare "aperto" multiple-spedizione in Python (da "aperto" Voglio dire "è possibile aggiungere più casi da ogni uovo"), con un'interfaccia più specifico partite prendendo la priorità su incontri specifici-less (Interface Le classi possono essere sottoclassi gli uni degli altri, e questo è esattamente quello che ci si sperare che farebbe.)

    Adattatori da un Interface possono essere chiamati con una sintassi molto bella, ISomething(object_to_adapt), o possono essere consultati tramite la funzione zope.component.getAdapter. Adattatori da più Interfaces devono essere guardato tramite la funzione zope.component.getMultiAdapter, che è un po 'meno bella.

    È possibile avere più di un adattatore per un dato insieme di Interfaces, differenziato per un name stringa che si fornisce al momento della registrazione l'adattatore. Le impostazioni predefinite di nome a "". Ad esempio, sono in realtà BrowserViews adattatori che si adattano dall'interfaccia che stanno registrati su e un'interfaccia che implementa classe HTTPRequest. È anche possibile cercare tutti delle schede che vengono registrate da una sequenza di Interfaces ad un altro Interface, utilizzando zope.component.getAdapters( (IAdaptFrom,), IAdaptTo ), che restituisce una sequenza di (nome, adattatore) coppie. Questo può essere usato come un bel modo per fornire i ganci per i plugin di si attaccano a.

    detto che volevo salvare tutti i messaggi e la configurazione del mio blog come un unico grande file XML. Creo un uovo my.blog.xmldump che definisce un IXMLSegment, e registra un adattatore da IBlogPost a IXMLSegment e un adattatore da IBlogConfiguration a IXMLSegment. Ora posso chiamare a seconda di quale adattatore è adatto per un oggetto che voglio serializzare scrivendo IXMLSegment(object_to_serialize).

    Potrei anche aggiungere più schede da varie altre cose da IXMLSegment dalle uova diverse my.blog.xmldump. ZCML ha una caratteristica in cui è possibile eseguire una particolare direttiva se e solo se è installato qualche uovo. Potrei usare questo per avere my.blog.rss registrare un adattatore da IRSSFeed a IXMLSegment sse my.blog.xmldump accade per essere installato, senza fare my.blog.rss dipendere my.blog.xmldump.

  4. Viewlets sono come piccoli BrowserViews che si può avere 'sottoscrivere' ad un punto particolare all'interno di una pagina. Non riesco a ricordare tutti i dettagli in questo momento, ma questi sono molto buono per le cose come plugin che si desidera visualizzare in una barra laterale.

    Non riesco a ricordare due piedi se sono parte di base di Zope e Plone. Suggerirei di non utilizzare Plone a meno che il problema che si sta tentando di risolvere in realtà ha bisogno di un vero e proprio CMS, dal momento che è un pezzo di software grande e complicato e che tende ad essere un po 'lento.

    Non è necessariamente effettivamente bisogno Viewlets in ogni caso, dal momento che BrowserViews possono chiamare l'un l'altro, utilizzando 'oggetto / @@ some_browser_view' in un'espressione TAL, oppure utilizzando queryMultiAdapter( (ISomething, IHttpRequest), name='some_browser_view' ), ma sono abbastanza piacevole a prescindere.

  5. Interfaces Marker. Un Interface marcatore è un Interface che non fornisce i metodi e attributi. È possibile aggiungere un marcatore Interface qualsiasi oggetto in fase di esecuzione utilizzando ISomething.alsoProvidedBy. Questo ti permette di, ad esempio, modificare quali adattatori andranno utilizzato su un particolare oggetto e che BrowserViews saranno definite su di esso.

Mi scuso che io non sono andato in dettaglio sufficiente per essere in grado di implementare ciascuno di questi esempi subito, ma che avrebbero preso circa un post sul blog ogni.

interfacce Zope possono fornire un modo utile per separare due parti di codice che non dovrebbe dipendere vicenda.

Supponiamo di avere un componente che sa come stampare un saluto nel modulo a.py:

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

E po 'di codice che ha bisogno di stampare un saluto nel modulo b.py:

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

Questa disposizione rende difficile scambiare il codice che gestisce il saluto senza toccare b.py (che potrebbe essere distribuito in un pacchetto separato). Invece, si potrebbe introdurre una terza c.py modulo che definisce un'interfaccia IGreeter:

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

Ora possiamo usare questo per disaccoppiare a.py e b.py. Invece di un'istanza di una classe Greeter, b.py ora chiedere un programma di utilità che fornisce l'interfaccia IGreeter. E a.py dichiarerà che la classe Greeter implementa l'interfaccia:

(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'

Non ho mai usato le interfacce Zope, ma si potrebbe non crei una metaclasse, che all'inizializzazione controlla i membri della classe contro l'interfaccia, e solleva un'eccezione di runtime se un metodo non è implementato.

Con Python non si dispone di altre opzioni. O hanno un "Compila" passo che ispeziona il codice, o dinamicamente controllarla in fase di esecuzione.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top