On 2/18/2013 7:18 PM, Steven D'Aprano wrote:
Terry Reedy wrote:

On 2/18/2013 6:47 AM, John Reid wrote:

I was hoping namedtuples could be used as replacements for tuples
 in all instances.

This is a mistake in the following two senses. First, tuple is a class
with instances while namedtuple is a class factory that produces
classes. (One could think of namedtuple as a metaclass, but it was not
implemented that way.)

I think you have misunderstood.

Wrong, which should be evident to anyone who reads the entire paragraph as the complete thought exposition it was meant to be. Beside which, this negative ad hominem comment is irrelevant to the rest of your post about the Liskov Substitution Principle.

The rest of the paragraph, in two more pieces:

Second, a tuple instance can have any length and
different instances can have different lengths. On the other hand, all
instances of a particular namedtuple class have a fixed length.

In other words, neither the namedtuple object nor any namedtuple class object can fully substitute for the tuple class object. Nor can instances of any namedtuple class fully substitute for instances of the tuple class. Therefore, I claim, the hope that "namedtuples could be used as replacements for tuples in all instances" is a futile hope, however one interprets that hope.

>> This affects their initialization.

Part of the effect is independent of initialization. Even if namedtuples were initialized by iterator, there would still be glitches. In particular, even if John's named tuple class B *could* be initialized as B((1,2,3)), it still could not be substituted for t in the code below.

>>> t = (1,2,3)
>>> type(t) is type(t[1:])
True
>>> type(t)(t[1:])
(2, 3)

As far as read access goes, B effectively is a tuple. As soon as one uses type() directly or indirectly (by creating new objects), there may be problems. That is because the addition of field names *also* adds a length constraint, which is a subtraction of flexibility.

---
Liskov Substitution Principle (LSP): I met this over 15 years ago reading debates among OOP enthusiasts about whether Rectangle should be a subclass of Square or Square a subclass of Rectangle, and similarly, whether Ostrich can be a legitimate subclass of Bird.

The problem I see with the LSP for modeling either abstract or concrete entities is that we in fact do define subclasses by subtraction or limitation, as well as by augmentation, while the LSP only allows the latter.

On answer to the conundrums above to to add Parallelepiped as a superclass for both Square and Rectangle and Flying_bird as an additional subclass of Bird. But then the question becomes: Does obeying the LSP count as 'necessity' when one is trying to follow Ockham's principle of not multiplying classes without necessity?

--
Terry Jan Reedy

--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to