namedtuple — applications of different type names

2019-06-28 02:41发布

问题:

The Python namedtuple factory function allows the name of the subclass it creates to be specified twice — first on the left side of the declaration and then as the first argument of the function (IPython 1.0.0, Python 3.3.1):

In [1]: from collections import namedtuple

In [2]: TypeName = namedtuple('OtherTypeName', ['item'])

All the examples I've seen on the docs.python.org site use an identical name in both positions. But it's possible to use different names, and they function differently:

In [3]: TypeName(1)
Out[3]: OtherTypeName(item=1)

In [4]: type(TypeName)
Out[4]: builtins.type

In [5]: type(OtherTypeName)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-8-6616c1214742> in <module>()
----> 1 type(OtherTypeName)

NameError: name 'OtherTypeName' is not defined

In []: OtherTypeName(1)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-9-47d6b5709a5c> in <module>()
----> 1 OtherTypeName(1)

NameError: name 'OtherTypeName' is not defined

I'm wondering what applications there might be for this functionality.

回答1:

You don't specify the name twice. You specify one "internal" name when calling namedtuple, and then you assign the resulting namedtuple type to a variable.

The one you specify as an argument to namedtuple is the resulting namedtuple type's own idea of its name --- that is, "what it calls itself". The thing on the left of the equals sign is just a normal Python variable to which you assign the namedtuple type.

You can only use the namedtuple you create if you assign it to something, and you can only use it via the name(s) you assign it to. Passing "OtherTypeName" as the "name" doesn't magically create a variable called OtherTypeName, which is why you get a NameError when you try to use the name OtherTypeName. The only real use of the name passed in to namedtuple ("OtherTypeName" in your case) is for displaying the resulting values.

Obviously, in many cases it's nice to have the variable you use to refer to the namedtuple be the same as its own internal name; it makes things less confusing. But you could have multiple variables pointing to the same namedtuple:

NameOne = namedtuple('OtherTypeName', ['item'])
NameTwo = NameOne

. . . or no variables pointing to it directly, and access it only via some container:

x = []
x.append(namedtuple('OtherTypeName', ['item']))
x[0] # this is your namedtuple

It's not so much that there are special "applications" of this as that the behavior itself is not special: a namedtuple is an object like any other, and creating an object isn't the same as creating a variable to refer to it.