[PyQt] thoughts about dip interfaces and python abstract base classes
Phil Thompson
phil at riverbankcomputing.com
Mon Mar 14 09:11:37 GMT 2011
On Sun, 13 Mar 2011 15:01:53 -0400, Darren Dale <dsdale24 at gmail.com>
wrote:
> I've been learning about python's abstract base classes at
> http://www.python.org/dev/peps/pep-3119/ and
> http://docs.python.org/py3k/library/abc.html . The PEP mentions that
> there is considerable overlap between ABCs and interfaces, and I'm
> rereading the dip documentation on interfaces now. If I understand
> correctly, dip's "implements" decorator is similar (perhaps based on)
> python's abstract base class "register" class method. Is it ever the
> case that dip classes actually subclass a dip interface, as python
> classes would subclass one or more abstract base class?
No (as in it's technically possible but you shouldn't do it). dip
interfaces can be sub-classed to created more specific interfaces, but the
only link to an implementation of the interface should be via the
@implements or @adapt class decorators. dip does support the ABC hooks
that
means that issubclass() and isinstance() can be used between an object
that
implements an interface and the interface itself.
It comes down to a personal philosophical choice - I much prefer
interfaces to ABCs. The problem with ABCs is that they encourage putting
the interface definition in the same place as a default implementation.
>From an architectural point of view I strongly believe that they should be
kept separate.
Interfaces have their own problems of course - mainly the need to repeat
the interface definition in an implementation. With Traits, for example,
an
implementation must contain a copy of the interface's attributes and
methods - which is error prone. dip is better because you don't have to
repeat the definition of the interface's attributes - they are injected
automatically into the implementation - but you still (for the moment
anyway) to have to repeat the interface's methods.
> Also, this morning I suggested on python-ideas a small tweak to
> python's builtin "property" which would allow an abstract properties
> to be declared using the decorator syntax. I thought it might be of
> interest to dip:
>
> import abc
>
> class Property(property):
>
> def __init__(self, *args, **kwargs):
> super(Property, self).__init__(*args, **kwargs)
> if (getattr(self.fget, '__isabstractmethod__', False) or
> getattr(self.fset, '__isabstractmethod__', False) or
> getattr(self.fdel, '__isabstractmethod__', False)):
> self.__isabstractmethod__ = True
>
> class C(metaclass=abc.ABCMeta):
> @Property
> @abc.abstractmethod
> def x(self):
> return 1
> @x.setter
> @abc.abstractmethod
> def x(self, val):
> pass
>
> try:
> # Can't instantiate C, C.x getter and setter are abstract
> c=C()
> except TypeError as e:
> print(e)
>
> class D(C):
> @C.x.getter
> def x(self):
> return 2
>
> try:
> # Can't instantiate D, the D.x setter is still abstract
> d=D()
> except TypeError as e:
> print(e)
>
> class E(D):
> @D.x.setter
> def x(self, val):
> pass
>
> # E is now instantiable
> print(E())
The way I would do this in dip would, instead of automatically injecting
any missing interface methods (which are all abstract by definition), I
would simply raise an exception. This would also address the point you
made in your second email.
Phil
More information about the PyQt
mailing list