[Python-3000] Traits/roles instead of ABCs (original) (raw)

Collin Winter collinw at gmail.com
Mon Apr 30 03:40:41 CEST 2007


[cc:-numpy]

On 4/29/07, Steven Bethard <steven.bethard at gmail.com> wrote:

On 4/29/07, Talin <talin at acm.org> wrote: > If it were technically possible, I would recommend that this PEP have to > run the same gauntlet that any other large library addition would, which > is to go through a long period of community feedback and criticism, > during which a large number of people actually attempt to use the > feature for real work.

This sounds like a pretty good reason to add isinstance() and issubclass(). Then the various ABCs can be distributed as third-party modules but can still make sure that things like isinstance(42, Real) and issubclass(int, Complex) are True (or whatever other assertions people want to make).

To me, having to mess with something as fundamental as isinstance() and issubclass() sounds like a pretty good reason to prefer a different solution over ABCs.

The mechanism I'm most familiar with for solving this problem (which, unless I've missed something, is, "how do I make sure this object does what I expect?") is Perl 6's roles system; if you know about Squeak Smalltalk's "traits" system, you're on the same page.

(I discussed this with Jeffery Yasskin at lunch the other day, and he seemed interested, so here follows a medium-length explanation of roles/traits.)

The idea is that we leave the traditional class system to manage an object's implementation and use a more-or-less orthogonal system to manage that same object's behavior.

Quoting from an article on Perl 6's roles,

""" A role is a named collection of behavior — a set of methods identified by a unique name. This resembles a class or a type, in that referring to the role refers to the combined set of behaviors, but it is more general than a class and more concrete than a type.

Put another way, a role is an assertion about a set of capabilities. """ [http://www.oreillynet.com/onlamp/blog/2006/08/roles_composable_units_of_obje.html]

The key part of traits/roles is that, because the system is separate from classes, you can do runtime role composition without a) mucking with bases, or b) making isinstance() and issubclass() squishy and ill-defined. By "runtime role composition", I mean it would be possible to do something like this at runtime:

py> int.implements(Ring)

or (depending on your spelling preferences)

py> Ring.implemented_by(int)

That is, it would be possible to distribute Jeffery's numeric kinds as a third-party library and still have them affect the built-in numeric types.

Now, how do roles/traits differ from interfaces? The primary distinction is that interfaces only define behavior, whereas roles can provide a dummy implementation. It would be possible for an Equality role to be defined like this (strawman syntax):

class Equality(Role): def eq(self, other): return not self != other

def ne(self, other): return not self == other

How would all this work in Python? Here's a collection of strawman proposals:

  1. For declaring roles statically, either class decorators or class arguments could be used:

@does(Complex) class A: ...

class A(does=Complex): ...

  1. I gave a strawman syntax proposal for runtime role composition above (modulo the method name): "Ring.done_by(int)" or "int.does(Ring)". (Perl 6 speaks in terms of "an object/class does a role".) Perl 6 also allows individual instances to do different roles than their class does, but I'm not sure we want to go that far.

  2. For querying role performance, something like this could work: "isdoneby(x, Ring)".

If class decorators and the "role.method(object)" spellings were used, I think this could probably be issued as a third-party package with no need to modify the interpreter at all.

For the interested, here's some more reading about roles/traits in roughly descending order of readability:

http://www.perlmonks.org/?node_id=384858 http://www.oreillynet.com/onlamp/blog/2006/08/roles_composable_units_of_obje.html http://www.iam.unibe.ch/~scg/Archive/Papers/Scha03aTraits.pdf

If there's interest in this, I could probably whip up a PEP before the deadline.

Collin Winter



More information about the Python-3000 mailing list