[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