I've just come up with an idea that I think may help clarify this discussion in a new way. I'm afraid the description is going to be a little long; but I'd appreciate it if you would bear with me and read the whole thing.
I'd like to start by coining a usage, namely the "abilities" of a type. By an ability, I mean a claim such as "Objects of type Foo are iterators" or "Objects of type Foo are copyable." I would like to use the word "ability" to refer to "iterator" and "copyable" in this context. When we say that a an object of a given class (or the class itself) has an ability, we are really saying that objects of that class behave in a particular way when used in a particular way. So, for example, when we say that x is an iterator (or x has the iterator ability), we mean that we can call x.next() to obtain successive values of a sequence, and that doing so for long enough will eventually raise StopIteration. So far, this discussion has been about the idea that a class should be able to acquire an ability by inheriting it. For quite a while, I thought this was an excellent idea; but now I'm not so sure. Here's why. I'll begin by explaining why I think it's an excellent idea. Suppose you have an object x of unknown type, and you want to know whether x is an iterator. Some people in this discussion have suggested that the Pythonic way to answer this question is to try to use it as an iterator and see if it raises an exception. The trouble with this technique is that it is destructive if it succeeds, because it consumes an element of the sequence. That means you can't use the technique until you have something to do with that first element, which rules out some plausible usages. I've raised this issue in discussion before, and gotten the response that the right way to deal with this problem is to use getattr(x,"next"). Doing so is certainly a way of determining whether x.next() is meaningful, but it doesn't offer a general way of telling whether an object has a given ability. For example, there is no analogous technique for determining whether len(x) will work without evaluating it. Nor is there a way to know whether someone just happened to define x.next() without intending to implement the iterator protocol. A good bit of the current discussion is about a way to solve this kind of problem, namely to define types that represent abilities. So, for example, if "iterator" were such a type, we could evaluate isinstance(x,iterator) to determine whether x is of a type that is intended to behave as an iterator. I've proposed this idea myself a while ago, and had been quite fond of it. Yes, there is an objection to this scheme, namely that existing user-defined iterator types would not automatically inherit from the "iterator" type; but maybe there is a way around that problem. However, I want to argue against this idea for a completely different reason: Inheritance should establish an "is-a" relationship, and that's not the right kind of relationship here. To put it bluntly: I can see no reason why the iterator type should have the iterator ability! More generally, I see no reason why a type that signals the presence of a given ability should itself possess that ability. Because if it does, then it becomes difficult to distinguish types that signal abilities from types that do not. In other words: Suppose that we have a family of types with names such as "iterator", "copyable", "equality_comparable", "comparable", and so on. Each of these types signals the corresponding ability. Some of these types may be related by inheritance. For example, I would expect "comparable" to inherit from "equality_comparable", because any type that is comparable had better be comparable for equality. It seems to me to make sense for the notion of "signaling an ability" to be an ability. In other words, the types in the last paragraph can all be used in a particular way, which is the hallmark of an ability. Now, suppose that every type that signals the presence of an ability inherits from "ability". Then we've just broken the whole ability system. Because if "iterator" inherits from "ability" and every iterator type inherits from "iterator", then every iterator is also able to signal the presence of an ability--and we most definitely do not want that! In other words, whether or not we choose to define a family of types that stand for particular abilities, I think we should not use inheritance as the mechanism for specifying that a particular class has a particular ability. I don't know what the mechanism should be, but it shouldn't be inheritance. Am I missing something? --Andrew Koenig _______________________________________________ Python-3000 mailing list Python-3000@python.org http://mail.python.org/mailman/listinfo/python-3000 Unsubscribe: http://mail.python.org/mailman/options/python-3000/archive%40mail-archive.com