Empecé a usar interfaces Zope en mi código y, a partir de ahora, en realidad son solo documentación. Los uso para especificar qué atributos debe tener la clase, implementarlos explícitamente en las clases apropiadas y buscarlos explícitamente donde lo espero. Esto está bien, pero me gustaría que hagan más si es posible, como verificar que la clase ha implementado la interfaz, en lugar de simplemente verificar que he dicho que la clase implementa la interfaz. He leído el zope wiki un par de veces, pero todavía no puedo ver mucho más uso de interfaces que lo que estoy haciendo actualmente. Entonces, mi pregunta es para qué otra cosa pueden usar estas interfaces, y cómo las usan para más.¿Propósito de las interfaces Zope?
Respuesta
En realidad, puede probar si su objeto o clase implementa su interfaz. Para que puede utilizar verify
módulo (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
Las interfaces también se pueden utilizar para configurar y probar invariantes. Puede encontrar más información aquí:
Nunca utilicé las interfaces de Zope, pero podría considerar escribir metaclass, que al inicializar comprueba los miembros de la clase con la interfaz y genera una excepción de tiempo de ejecución si no se implementa un método.
Con Python no tiene otras opciones. O tiene un paso de "compilación" que inspecciona su código o lo inspecciona dinámicamente en tiempo de ejecución.
interfaces de Zope pueden proporcionar una forma útil para desacoplar dos piezas de código que no debe depender el uno del otro.
Digamos 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 para imprimir un saludo en b.py módulo:
>>> Greeter().greet()
'Hello'
Esta disposición hace que sea difícil cambiar el código que maneja el saludo sin tocar b.py (que podría distribuirse en un paquete separado). En su lugar, se podría introducir una 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 instanciar una clase Greeter, b.py ahora solicitará una utilidad que proporcione la interfaz IGreeter. Y a.py declarará que la clase Greeter implementa esa interfaz:
(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'
para completar, ¿puede agregar un ejemplo para los adaptadores? – sureshvv
¿Qué quiere decir con 'cambiar el código que maneja el saludo'? ¿Cómo se resuelve este problema usando la interfaz como se mostró arriba? –
En 'b.py' él está recibiendo una sorpresa, pero él no ha importado' a'. es decir: no hay 'de un Greeter de importación' – Kurt
donde trabajo, que utilizan interfaces de modo que podemos utilizar ZCA, o la Zope Component Architecture, que es todo un marco para la fabricación de componentes que son intercambiables y conectable usando Interface
s. Usamos ZCA para que podamos hacer frente a todo tipo de personalizaciones por cliente sin tener que forzar nuestro software o tener todos los bits por cliente arruinando el árbol principal. La wiki de Zope a menudo es bastante incompleta, desafortunadamente. Hay una buena explicación de la mayoría de las características de ZCA en su ZCA's pypi page.
No uso Interface
s para nada como comprobar que una clase implementa todos los métodos para un Interface
dado.En teoría, eso podría ser útil cuando agrega otro método a una interfaz, para verificar que haya recordado agregar el nuevo método a todas las clases que implementan la interfaz. Personalmente, prefiero crear una nueva Interface
sobre la modificación de una anterior. La modificación de la antigua Interfaces
suele ser una muy mala idea una vez que están en los huevos que se han lanzado a pypi o al resto de su organización.
Una nota rápida sobre la terminología: clases implementanInterface
s, y objetos (instancias de clases) proporcionanInterface
s. Si desea verificar un Interface
, escriba ISomething.implementedBy(SomeClass)
o ISomething.providedBy(some_object)
.
Por lo tanto, a ejemplos de donde ZCA es útil. Imaginemos que estamos escribiendo un blog, usando ZCA para hacerlo modular. Tendremos un objeto BlogPost
para cada publicación, que proporcionará una interfaz IBlogPost
, todo definido en nuestro huevo handy-dandy my.blog
. También almacenaremos la configuración del blog en los objetos BlogConfiguration
que proporcionan IBlogConfiguration
. Usando esto como punto de partida, podemos implementar nuevas características sin tener que tocar el my.blog
.
La siguiente es una lista de ejemplos de cosas que podemos hacer al usar ZCA, sin tener que alterar el huevo base my.blog
. Yo o mis compañeros de trabajo hemos hecho todas estas cosas (y las hemos encontrado útiles) en proyectos reales para clientes, aunque no estábamos implementando blogs en ese momento. :) Algunos de los casos de uso aquí podrían resolverse mejor por otros medios, como un archivo CSS de impresión.
Adición de puntos de vista adicionales (
BrowserView
s, por lo general 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 llamadoprint
paraIBlogPost
, que representa la entrada del blog a través de un Zope Page Template diseñado para producir HTML que se imprime muy bien. EseBrowserView
aparecería en la URL/path/to/blogpost/@@print
.Mecanismo de suscripción de eventos en Zope. Digamos que quiero publicar feeds RSS, y quiero generarlos con anticipación en lugar de a pedido. Podría crear un huevo
my.blog.rss
. En ese huevo, registraría un suscriptor para eventos que proporcionan IObjectModified (zope.lifecycleevent.interfaces.IObjectModified
), en objetos que proporcionanIBlogPost
. A ese suscriptor se le llamaría cada vez que cambiara un atributo en cualquier cosa que proporcionaraIBlogPost
, y podría usarlo para actualizar todos los canales RSS en los que debería aparecer la publicación del blog.En este caso, podría ser mejor tener un
IBlogPostModified
evento que se envía al final de cada uno de losBrowserView
s que modifican publicaciones de blog, ya queIObjectModified
se envía una vez en cada cambio de atributo único, lo que puede ocurrir con demasiada frecuencia por el rendimiento.Adaptadores. Los adaptadores son efectivamente "moldes" de una interfaz a otra. Para geeks de lenguaje de programación: los adaptadores Zope implementan el despacho múltiple "abierto" en Python (con "abierto" quiero decir "puedes agregar más casos de cualquier huevo"), con coincidencias de interfaz más específicas que tienen prioridad sobre las menos específicas (
Interface
las clases pueden ser subclases de unos a otros, y esto hace exactamente lo que usted esperaría que lo haría.)adaptadores de un
Interface
se pueden llamar con una sintaxis muy agradable,ISomething(object_to_adapt)
, o se pueden consultar a través de la funciónzope.component.getAdapter
.Los adaptadores de múltiplesInterface
s deben buscarse a través de la funciónzope.component.getMultiAdapter
, que es ligeramente menos bonita.Puede tener más de un adaptador para un conjunto dado de
Interface
s, diferenciado por una cadenaname
que proporciona al registrar el adaptador. El nombre predeterminado es""
. Por ejemplo,BrowserView
s son en realidad adaptadores que se adaptan desde la interfaz en la que están registrados y una interfaz que implementa la clase HTTPRequest. También puede buscar todos los de los adaptadores que están registrados de una secuencia deInterface
a otraInterface
, usandozope.component.getAdapters((IAdaptFrom,), IAdaptTo)
, que devuelve una secuencia de pares (nombre, adaptador). Esto se puede utilizar como una muy buena manera de proporcionar ganchos para que los complementos se adhieran.Digamos que quería guardar todas las publicaciones y la configuración de mi blog como un gran archivo XML. Creo un huevo
my.blog.xmldump
que define unIXMLSegment
, y registra un adaptador deIBlogPost
aIXMLSegment
y un adaptador deIBlogConfiguration
aIXMLSegment
. Ahora puedo llamar al adaptador que sea apropiado para algún objeto que quiera serializar escribiendoIXMLSegment(object_to_serialize)
.Incluso podría agregar más adaptadores de varias otras cosas a
IXMLSegment
de huevos que no seanmy.blog.xmldump
. ZCML tiene una función en la que puede ejecutar una directiva particular si y solo si se instala un huevo. Podría usar esto para tenermy.blog.rss
registrar un adaptador deIRSSFeed
aIXMLSegment
si se instalamy.blog.xmldump
, sin quemy.blog.rss
dependa demy.blog.xmldump
.Viewlet
s son como pequeñosBrowserView
s que puede tener 'suscribirse' a un lugar en particular dentro de una página. No puedo recordar todos los detalles en este momento, pero estos son muy buenos para cosas como complementos que desea que aparezcan en una barra lateral.No puedo recordar si son parte de la base Zope o Plone. Recomendaría no usar Plone, a menos que el problema que estás tratando de resolver necesite realmente un CMS real, ya que es un software grande y complicado y tiende a ser un poco lento.
que no necesariamente necesitan realmente
Viewlet
s todos modos, yaBrowserView
s puedan llamarse entre sí, ya sea mediante el uso de 'objeto/@@ some_browser_view' en una expresión TAL, o mediante el uso dequeryMultiAdapter((ISomething, IHttpRequest), name='some_browser_view')
, pero son bastante agradable sin tener en cuenta .Marcador
Interface
s. Un marcadorInterface
es unInterface
que no proporciona ningún método ni atributo. Puede agregar un marcadorInterface
a cualquier objeto en tiempo de ejecución usandoISomething.alsoProvidedBy
. Esto le permite, por ejemplo, modificar qué adaptadores se utilizarán en un objeto particular y cuáles se definirán en élBrowserView
s.
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.
¡Grandes explicaciones, gracias por esto! –
+1 - es realmente una pena que mucha gente no sepa que los adaptadores son realmente un mecanismo de envío múltiple/multimétodos. –
+1 como un buen ejemplo y cualquiera que sea el 40-50% de las respuestas que pude darles sentido. Tantas terminologías nuevas –
- 1. ¿Cuál es el propósito de las interfaces en php?
- 2. Comprensión de las interfaces
- 3. Exportación de una carpeta zope con python
- 4. ¿Codificando a las interfaces?
- 5. Autorreferencia en las interfaces
- 6. Propósito de las transacciones anidadas
- 7. Anotaciones en las interfaces?
- 8. Importancia de las interfaces C#
- 9. PHPUnit, las interfaces burlado, y instanceof
- 10. ¿Cuándo se necesitan las interfaces?
- 11. Destructores virtuales para las interfaces
- 12. Parámetros opcionales para las interfaces
- 13. C# Cómo usar las interfaces
- 14. ¿Deberían las entidades implementar interfaces?
- 15. ¿Deben las interfaces definir propiedades?
- 16. Las estructuras, interfaces y boxeo
- 17. Propósito de las protecciones de encabezado
- 18. Método de igualdad en las interfaces
- 19. consulta acerca de las interfaces en Java
- 20. métodos de constructor en las interfaces
- 21. ¿El código de las interfaces vacías huele?
- 22. Herencia en las interfaces de colección Java
- 23. ¿Las interfaces de PHP tienen propiedades?
- 24. ¿Las clases abstractas de Do/can reemplazan las interfaces?
- 25. Delphi Rtti: Explore las propiedades de las interfaces?
- 26. ¿Cómo se obtienen y configuran las cookies en Zope y Plone?
- 27. ¿Por qué implementamos las interfaces recursivamente?
- 28. ¿Son necesarias las interfaces en JavaScript?
- 29. modelo MVC unión a las interfaces
- 30. ¿Equivalente a las interfaces Java en C++?
Genial, supongo que mi solución de escribir tus propias pruebas es innecesaria. Aunque todavía podría ser útil tener excepciones de tiempo de ejecución en lugar de confiar en un caso de prueba, esta es una mejor solución. –
Gracias, esto es exactamente lo que estaba buscando. Estaba seguro de que había alguna manera de hacer esto, pero no tenía idea de cómo. – Nikwin
Además, echa un vistazo a zope.esquema: proporciona una forma más detallada de especificar tipos. Y también existe zope.interface.invariant, que se puede usar para definir los invariantes reales que la interfaz debe respetar. –