Propósito de Zope interfaces?
-
22-09-2019 - |
Pregunta
Me han empezado a utilizar las interfaces de Zope en mi código, ya partir de ahora, son realmente única documentación. Las uso para especificar qué atributos de la clase debe poseer, aplicar de forma explícita en las clases correspondientes y comprobar explícitamente para ellos donde espero una. Esto está muy bien, pero me gustaría que hagan más si es posible, como en realidad verificar que la clase ha implementado la interfaz, en lugar de simplemente verificar que he dicho que implementa la interfaz de clase. He leído el zope wiki un par de veces, pero todavía no puedo ver mucho más el uso de las interfaces que lo que estoy haciendo actualmente. Por lo tanto, mi pregunta es ¿qué más se puede utilizar para estas interfaces, y cómo se les utilice para más.
Solución
En realidad se puede comprobar si el objeto o la clase implementa la interfaz.
Para que pueda utilizar el módulo verify
(se suele utilizar en las pruebas):
>>> 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
Interfaces también se puede utilizar para configurar y probar invariantes. Puede encontrar más información aquí:
Otros consejos
Donde trabajo, utilizamos interfaces de modo que podemos utilizar ZCA, o la href="http://www.muthukadan.net/docs/zca.html" rel="noreferrer"> arquitectura de componentes de Zope , que es todo un marco para la fabricación de componentes que son intercambiables y conectables utilizando Interface
s. Utilizamos ZCA para que podamos hacer frente a todo tipo de personalizaciones por cliente sin necesidad de tener que desembolsar nuestro software o tener todos los muchos bits por cliente que ensucian el árbol principal. El wiki Zope es a menudo bastante incompleta, por desgracia. Hay una explicación buena, pero-escueto de la mayor parte de las características de ZCA en su de ZCA página PyPI .
No consumo Interface
s para nada como la comprobación de que una clase implementa todos los métodos para una Interface
dado. En teoría, eso puede ser útil cuando se agrega otro método a una interfaz, para comprobar que ha recordado que añadir el nuevo método a todas las clases que implementan la interfaz. Personalmente prefiero fuertemente para crear un nuevo Interface
sobre la modificación de una vieja. Modificó el antiguo Interfaces
es por lo general una muy mala idea una vez que están en los huevos que han sido liberados a PyPI o para el resto de su organización.
Una nota rápida sobre la terminología: clases implementan Interface
s, y objetos (instancias de clases) proporcionar Interface
s. Si desea comprobar si existe una Interface
, lo haría bien ISomething.implementedBy(SomeClass)
escritura o ISomething.providedBy(some_object)
.
Por lo tanto, hasta ejemplos en los que ZCA es útil. Supongamos que estamos escribiendo un blog, utilizando la ZCA para que sea modular. Tendremos un objeto BlogPost
para cada puesto, lo que proporcionará una interfaz IBlogPost
, todos definidos en nuestro práctico-excelente huevo my.blog
. También vamos a almacenar la configuración del blog en el BlogConfiguration
objetos que proporcionan IBlogConfiguration
. Usando esto como punto de partida, podemos implementar nuevas características sin necesidad de tener que tocar my.blog
en absoluto.
La siguiente es una lista de ejemplos de cosas que podemos hacer mediante el uso de ZCA, sin tener que alterar el huevo my.blog
base. Yo o mis compañeros de trabajo he hecho todas estas cosas (y las encontraron útil) en proyectos reales para-cliente, aunque no estábamos implementando los blogs en el momento. :) Algunos de los casos de uso aquí podría ser mejor resueltos por otros medios, como por ejemplo un archivo CSS de impresión.
-
La adición de puntos de vista adicionales (por lo general,
BrowserView
s registrados en ZCML con la directivabrowser:page
) a todos los objetos que proporcionanIBlogPost
. Podría hacer un huevomy.blog.printable
. Ese huevo registraría un BrowserView llamadaprint
paraIBlogPost
, lo que hace que la entrada de blog a través de un Zope plantilla de página diseñado para producir HTML que imprime muy bien.BrowserView
que aparecería entonces en el/path/to/blogpost/@@print
URL. -
El mecanismo de suscripción de eventos en Zope. Digamos que quiero publicar los canales RSS, y yo quiero generar por adelantado en lugar de por encargo. Podría crear un huevo
my.blog.rss
. En ese huevo, me inscribo a un abonado para los eventos que proporcionan IObjectModified (zope.lifecycleevent.interfaces.IObjectModified
), en los objetos que proporcionanIBlogPost
. Ese abonado conseguiría llamará cada vez que un atributo cambia en nada proporcionandoIBlogPost
, y pude utilizarlo para actualizar todos los canales RSS que el blog debe aparecer en.En este caso, podría ser mejor tener un evento
IBlogPostModified
que se envía al final de cada una de las entradas del blogBrowserView
s que modificar, ya que se obtieneIObjectModified
nt una vez en cada cambio de atributo -. que podría ser demasiado a menudo por el bien de rendimiento -
adaptadores. Los adaptadores son efectivamente "moldes" de una interfaz a otra. Para la programación de los frikis del lenguaje: adaptadores Zope implementan "abierta" múltiple de despacho en Python (por "abierta" me refiero a "puede agregar más casos de cualquier huevo"), con partidos interfaz más específicos teniendo prioridad sobre los partidos menos específicas (
Interface
las clases pueden ser subclases de unos a otros, y esto es exactamente lo que usted esperaría que lo haría.)Adaptadores de una
Interface
se puede llamar con una sintaxis muy agradable,ISomething(object_to_adapt)
, o se puede consultar a través de lazope.component.getAdapter
función. Adaptadores de múltiplesInterface
s han de ser consultados a través de lazope.component.getMultiAdapter
función, que es un poco menos bonito.Puede tener más de un adaptador para un conjunto dado de
Interface
s, diferenciados por unname
cadena que usted proporciona cuando se registra el adaptador. El nombre por defecto es""
. Por ejemplo,BrowserView
s son en realidad los adaptadores que se adaptan a la interfaz que están registradas en y una interfaz que los HTTPRequest implementa la clase. También puede mirar hacia arriba todos de los adaptadores que se registran a partir de una secuencia a otraInterface
sInterface
, utilizandozope.component.getAdapters( (IAdaptFrom,), IAdaptTo )
, que devuelve una secuencia de (nombre, adaptador de pares). Esto puede ser usado como una forma muy agradable para proporcionar ganchos para los plugins para adherirse a.Decir que quería salvar a todos los mensajes y la configuración de mi blog como un gran archivo XML. Creo un huevo
my.blog.xmldump
que define unaIXMLSegment
, y registra un adaptador deIBlogPost
aIXMLSegment
y un adaptador deIBlogConfiguration
aIXMLSegment
. Ahora puedo llamar a cualquier adaptador es apropiado para un objeto que desea realizar una serie escribiendoIXMLSegment(object_to_serialize)
.Incluso podría añadir más adaptadores de varias otras cosas que
IXMLSegment
de huevos distintos demy.blog.xmldump
. ZCML tiene una característica que pueda realizar una directiva particular, si y sólo si se ha instalado un poco de huevo. Podría utilizar esto para tenermy.blog.rss
registrar un adaptador deIRSSFeed
aIXMLSegment
si y sólo simy.blog.xmldump
que se encuentren instaladas, sin hacermy.blog.rss
dependerá demy.blog.xmldump
. -
Viewlet
s son como pequeñosBrowserView
s que se puede tener 'suscribir' a un punto en particular dentro de una página. No puedo recordar todos los detalles en este momento, pero estos son muy buenos para cosas como plugins que desea que aparezca en una barra lateral.No puedo recordar la ligera si son parte de la base de Zope o Plone. Yo recomendaría contra el uso de Plone a menos que el problema que se está tratando de resolver realmente necesita un verdadero CMS, ya que es una pieza grande y complicado de software y tiende a ser un poco lento.
Usted no necesariamente necesita realmente
Viewlet
s todos modos, yaBrowserView
s puedan llamarse entre sí, ya sea mediante el uso de '/ @@ some_browser_view objeto' TAL en una expresión, o mediante el uso dequeryMultiAdapter( (ISomething, IHttpRequest), name='some_browser_view' )
, pero son bastante agradable sin tener en cuenta. -
Interface
s Marker. AInterface
marcador es unInterface
que no proporciona métodos y atributos. Puede añadir un marcador deInterface
cualquier objeto en tiempo de ejecución utilizandoISomething.alsoProvidedBy
. Esto le permite, por ejemplo, el alter qué adaptadores se acostumbrará en un objeto particular, y queBrowserView
s se definirá en él.
Me disculpo que no he entrado en detalles suficientes para poder llevar a cabo cada uno de estos ejemplos de inmediato, sino que tomaría aproximadamente una entrada de blog cada uno.
interfaces de Zope puede proporcionar una forma útil para desacoplar dos piezas de código que no debe depender de uno al otro.
Supongamos que tenemos un componente que sabe cómo imprimir un saludo en a.py módulo:
>>> class Greeter(object):
... def greet(self):
... print 'Hello'
Y un código que necesita imprimir un saludo en b.py módulo:
>>> Greeter().greet()
'Hello'
Esta disposición hace que sea difícil que cambiar el código que maneja el saludo sin tocar b.py (que podría ser distribuido en un paquete separado). En lugar de ello, podríamos introducir tercera c.py módulo que define una interfaz IGreeter:
>>> from zope.interface import Interface
>>> class IGreeter(Interface):
... def greet():
... """ Gives a greeting. """
Ahora podemos usar esto para desacoplar a.py y b.py. En lugar de crear instancias de una clase Greeter, b.py ahora pedir una utilidad que proporciona la interfaz IGreeter. Y a.py declarará que implementa el interfaz de la clase Greeter que:
(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'
Nunca he usado interfaces de Zope, pero es posible que no hacer una metaclase , que en los cheques de inicialización de los miembros de la clase en contra de la interfaz, y plantea una excepción de tiempo de ejecución si no se implementa un método.
Con Python que no tienen otras opciones. O bien tienen un paso "compilación" que inspecciona su código, o dinámicamente en tiempo de ejecución inspeccionarlo.