protocols, inheritance and polymorphism

Dan Perl danperl at rogers.com
Tue Nov 23 18:47:14 EST 2004


"Donn Cave" <donn at u.washington.edu> wrote in message 
news:donn-F39B72.13183123112004 at gnus01.u.washington.edu...
> In article <tqadnT2kAIXJEj7cRVn-hA at rogers.com>,
> "Dan Perl" <danperl at rogers.com> wrote:
>
>> "Donn Cave" <donn at u.washington.edu> wrote in message
>> news:donn-F6A9D8.11153623112004 at gnus01.u.washington.edu...
>> > In article <YWKod.137814$HA.44609 at attbi_s01>,
>> > Steven Bethard <steven.bethard at gmail.com> wrote:
> ...
>> >> The point here is that I'm using isinstance here because I *know* 
>> >> there
>> >> are objects out there that, unlike Bunch objects, may have 
>> >> 'attributes'
>> >> not stored in their __dict__, and I *know* they might get passed to
>> >> Bunch.update.  Since I can't appropriately support their use, I want 
>> >> the
>> >> user to be notified of this (with the TypeError).
> ...
>> > I don't really see that isinstance() was necessary in principle
>> > here.  Not that it makes any difference to me, but it looks like
>> > you created this problem by defining these semantics in Bunch
>> > but failing to assign any identifiable attribute - we could in
>> > principle make another unrelated class "quack like a Bunch",
>> > but we'd have no way to inform your update function of this.
>>
>> I'm not sure what you mean by an "identifiable attribute", but I think we
>> are going back to an issue I pointed out in another posting in this 
>> thread.
>> It makes a huge difference whether your code is something that only you 
>> are
>> using and changing during the next few weeks or it's an off-the-shelf
>> library that will be maintained and changed for years from now and will 
>> be
>> used by many clients.  What is "identifiable" to you (or even to someone 
>> in
>> the next cubicle) for the next few weeks may not be identifiable a few 
>> years
>> from now or to someone who downloaded your module from the web.
>
> I wasn't really worried about people yet.  Perhaps I should have
> said more simply that there is no attribute, period, for this.
> Instead, in effect, the (base) class itself is used as that attribute.
> That's an unnecessary limitation, because we can easily support
> the required semantics from an unrelated class.
>
> I must have missed your post, but I infer that you're claiming that
> subtype polymorphism is easier to comprehend.  It wouldn't have
> occurred to me.  I do think the current situation is a little
> defective when it comes to reasoning about complicated code, but
> I don't think subtyping is a very obvious way to define interfaces.
> On one hand, it obviously isn't true that all objects that might
> support an interface must inherit that support from a common base,
> and it also isn't true that all objects derived from a common base
> reliably support that interface.  How easy would it be to inherit
> from "Bunch" and add some feature that confounds that function we
> saw earlier with the isinstance()?

I was rather saying that subtype polymorphism (through inheritance, rather 
than protocols) and checking with isinstance is safer.  You are right that 
inheritance is not foolproof either.  But if someone is inheriting from your 
base class, they are bound to be more aware of the interface and to be more 
careful when overriding an attribute that would completely change the 
behavior of their objects.  A protocol can be broken in many other ways.  In 
the case of a well known protocol like iterators most people know better 
than to use the name "next" for any attribute other than a method used for 
iteration.  But if you create a little known protocol interface with a 
poorly chosen attribute name like "x" it is very likely that someone is 
going to use the same name in a class for some attribute that is completely 
different (e.g., data instead of a method).  And if they are not explicitly 
inheriting from a base class they may never be aware they are obfuscating a 
behavior that is being used somewhere in their code.  Note that I said 
"explicitly inheriting", which infers that people can make the same kind of 
mistakes also if they inherit from some class without knowing it.

This discussion feels to me like deja vu.  It's a kind of philosophical 
discussion in which I've been involved before, with me on this side of the 
argument and with other people being on the side that says that "python is 
designed for people who rely more on their users and for users who are more 
reliable, the other people should use other languages" (my own 
paraphrasing).  I'm not saying this with any disrespect toward the other 
side.  After all, this is probably inherent in a dynamically typed language, 
and dynamic typing has other advantages instead.  It's just something I 
still have to get used to: what is python good for, in what kind of 
applications it should be used and when should you just use a different 
(perhaps a strongly typed) language.

Dan

>   Donn Cave, donn at u.washington.edu 





More information about the Python-list mailing list