[Python-3000] Revised PEP 3119 (Abstract Base Classes)
Nick Coghlan
ncoghlan at gmail.com
Wed May 16 12:10:27 CEST 2007
Collin Winter wrote:
>>>> MyABC.register(list)
>>>> isinstance([], MyABC)
> True # Good, I can call foo()
>>>> [].foo()
> Traceback (most recent call last):
> AttributeError: 'list' object has no attribute 'foo'
>
> Have I missed something? It would seem that when dealing with ABCs
> that provide concrete methods, "isinstance(x, SomeABC) == True" is
> useless.
You've missed something - the declaration in your example that list is
compliant with the example ABC when that is not in fact the case is an
out-and-out bug that leads directly to the exception on the last line.
I can construct an identical example for PEP 3133:
class MyRole(metaclass=Role):
def foo(self): # An abstract method
pass
@performs_role(MyRole)
class MyRoleMixin(object):
def foo(self): # A concrete method
return 5
class MyClass(MyRoleMixin): # Use Mixin to perform the Role
pass
.>>> a = MyClass()
.>>> performs(a, MyRole)
True # Good, I can call foo()
.>>> a.foo()
5
.>>> performs_role(MyRole)(list) # This assertion is WRONG!
.>>> performs([], MyRole)
True # Good, I can call foo()
.>>> [].foo()
Traceback (most recent call last):
AttributeError: 'list' object has no attribute 'foo'
One of the key things that PEP 3119 does is to permit a single ABC to
handle both of the jobs that PEP 3133 assigns to separate Role and Mixin
classes.
When implementing a PEP 3119 style interface you have two options -
inherit from the ABC and benefit from its mixin characteristics, or else
do a post-hoc registration and implement everything yourself.
Enforcing an explicit Role/Mixin distinction the way that PEP 3133 does
just makes the interface developer repeat themselves - once to write the
Role and then again to write a Mixin that provides the concrete methods
which can be defined entirely in terms of other methods in the interface.
After that extra work, the user of the interface still has the same two
options - inherit from the Mixin and benefit from the partial
implementation, or do the post-hoc registration and full implementation.
Equivalent expressiveness and significantly less typing gives me a
strong personal preference towards the PEP 3119 approach. The
improvements in proxy object support and keeping isinstance() as the one
obvious way to introspect interfaces are also nice bonuses.
Cheers,
Nick.
--
Nick Coghlan | ncoghlan at gmail.com | Brisbane, Australia
---------------------------------------------------------------
http://www.boredomandlaziness.org
More information about the Python-3000
mailing list