Differences creating tuples and collections.namedtuples

Terry Reedy tjreedy at udel.edu
Wed Feb 20 04:38:32 CET 2013


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




More information about the Python-list mailing list