Yo personalmente uso interfaces mucho en conjunto con Zope Component Architecture (ZCA). La ventaja no es tanto tener interfaces sino poder usarlas con adaptadores y utilidades (singletons).
E.g. podrías crear un adaptador que pueda tomar una clase que implemente ISomething pero la adapte a la interfaz ISomethingElse. Básicamente es un envoltorio.
la clase original sería:
class MyClass(object):
implements(ISomething)
def do_something(self):
return "foo"
entonces se puede imaginar interfaz ISomethingElse tiene una do_something_else método(). Un adaptador podría tener este aspecto:
class SomethingElseAdapter(object):
implements(ISomethingElse)
adapts(ISomething)
def __init__(self, context):
self.context = context
def do_something_else():
return self.context.do_something()+"bar"
A continuación registraría que el adaptador con el registro de componentes y, a continuación, puede utilizar de esta manera:
>>> obj = MyClass()
>>> print obj.do_something()
"foo"
>>> adapter = ISomethingElse(obj)
>>> print adapter.do_something_else()
"foobar"
Lo que le da es la capacidad de extender la clase original con funcionalidad que la clase no proporciona directamente. Puede hacerlo sin cambiar esa clase (puede estar en un producto/biblioteca diferente) y simplemente puede intercambiar ese adaptador por una implementación diferente sin cambiar el código que lo utiliza. Todo se hace mediante el registro de componentes en tiempo de inicialización.
Esto, por supuesto, es principalmente útil para marcos/bibliotecas.
Creo que toma tiempo acostumbrarse, pero realmente ya no quiero vivir sin él. Pero como se dijo antes, también es cierto que debe pensar exactamente dónde tiene sentido y dónde no. Por supuesto, las interfaces por sí mismas también pueden ser útiles como documentación de la API. También es útil para pruebas unitarias donde puedes probar si tu clase realmente implementa esa interfaz. Y por último pero no menos importante, me gusta comenzar escribiendo la interfaz y algunos doctests para tener la idea de lo que realmente voy a codificar.
Para obtener más información, puede consultar mi little introduction to it y hay un quite extensive description of it's API.
"exigir que se overriden el método que se llamará": some_other_method pero se puede llamar ISomething()() – Miles
no parece muy Pythonic a mí.. –