[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