[Python-ideas] A namedtuple literal.

Steven D'Aprano steve at pearwood.info
Wed Apr 2 23:27:00 CEST 2014


On Wed, Apr 02, 2014 at 06:34:00PM +0200, Philipp A. wrote:
> 2014-04-02 17:20 GMT+02:00 Yury Selivanov <yselivanov.ml at gmail.com>:
> 
> > But when you have a key name defined in a variable, you’ll need to do
> > 
> > key = 'spam'
> > o = {}
> > o[key] = 'ham'
> > 
> > Where in Python, you’d simply write {key: ‘ham’}.
> > 
> > So for Python, I think that having unquoted keys in literals is a 
> > bad idea.
> 
> i totally agree for dicts, but here i don’t. instead i’d require unquoted
> keys like in kwargs.

These would be reasonable points to consider if the idea of literal 
namedtuple syntax was a serious idea to consider, but I don't think it 
is. Please look again at Eric's original post, and take note of the last 
thing he says, and remember that there is a tradition in Anglo-American 
culture of making "April Fools" jokes and other non-serious suggestions.

namedtuple, as it exists, creates a class, which you then instantiate. 
It's a factory function, not a class itself:

py> from collections import namedtuple
py> type(namedtuple)
<class 'function'>

 
But Eric's suggestion skips creating a distinct class and gives you an 
instance straight away. So what class will the instance belong to? There 
are three obvious possibilities, and they're all unfortunate:


(1) every instance is a singleton of a unique class;

(2) there is a single NamedTuple class that every instance belongs to;

(3) the namedtuple literal has to cache the keys it has seen, and return 
the same class when given the same keys in the same order.


None of them are ideal; #3 means that if module a creates a namedtuple, 
and module b creates a namedtuple that just happens to use the same 
field names, they will have the same type. Most of the time that will 
not matter, but occasionally it will lead to problems.

(e.g. suppose module a enforces some constraint on the field values, but 
module b does not. Then if a namedtuple from b somehow gets passed to 
module a, which does an isinstance type check to validate the 
namedtuple, the constraint will be broken).

#2 on the other hand means that:

    vector = (x: 2.3, y: -4.2, z: 1.7)
    colour = (red: 100, green: 5, blue: 203)

will be considered the same type. For something meant to be considered 
as a record or struct, I think that's a bad idea.

#1 on the other hand means that:

    p = (x: 2, y: 3)
    q = (x: 2, y: 3)

will be considered different types, which is surely going to come to a 
big surprise to most people.

Of the three scenarios, I think #3 is the least worst. But I don't 
really like it.


>     2.
> 
>    i don’t actually want this to be something with dynamic keys.
> 
>    it’s supposed to be a namedtuple, and namedtuples are static as well
>    regarding their keys.

I'm not entirely sure what you mean by this. The namedtuple factory 
function accepts dynamic keys, not just literals:

py> from collections import namedtuple
py> name = 'spam'
py> K = namedtuple('K', (name, 'eggs', 'cheese'))
py> K._fields
('spam', 'eggs', 'cheese')


I don't think literal syntax should be any more restrictive:

name = "spam"
t = (name: 1, 'eggs': 2, 'cheese': 3)
assert t._fields == ('spam', 'eggs', 'cheese')
assert getattr(t, name) == 1

But now I'm also guilty of ignoring Eric's warning not to take the 
suggestion too seriously.


-- 
Steven


More information about the Python-ideas mailing list