I read the official documentation of collections.namedtuple
today and found _tuple
in the __new__
method. I did not find where the _tuple
was defined.
You can try running the code below in Python, it does not raise any error.
>>> Point = namedtuple('Point', ['x', 'y'], verbose=True)
class Point(tuple):
'Point(x, y)'
__slots__ = ()
_fields = ('x', 'y')
def __new__(_cls, x, y):
'Create a new instance of Point(x, y)'
return _tuple.__new__(_cls, (x, y)) # Here. Why _tuple?
Update: What are the advantages of
from builtins import property as _property, tuple as _tuple
Is that just to let tuple
be a protected value? Am I right?
From the generic source code (you can see the source code generated for this specific namedtuple by printing Point._source
):
from builtins import property as _property, tuple as _tuple
So _tuple
here is just an alias for the built-in tuple
type:
In [1]: from builtins import tuple as _tuple
In [2]: tuple is _tuple
Out[2]: True
collections.namedtuple
was added in Python 2.6.0. This was the initial source code for the __new__
method:
def __new__(cls, %(argtxt)s):
return tuple.__new__(cls, (%(argtxt)s)) \n
The thing is, the source code is in string. They later format it using % locals()
. If tuple
was listed in argtxt
, then tuple.__new__
would have called the __new__
method of whatever the tuple
field contained. In contrast, _tuple
works as expected because namedtuple
doesn't allow field names starting with _
.
The bug was fixed in Python 2.6.3 release (see the changelog - collections.namedtuple() was not working with the following field names: cls, self, tuple, itemgetter, and property).