Is there a use for _tuple in Python?

2019-06-22 06:54发布

问题:

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?

回答1:

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).