I see that the Python syntax for a namedtuple is:
Point = namedtuple('Point', ['x', 'y'])
Why isn't it simpler like so:
Point = namedtuple(['x','y'])
Its less verbose,
In general, objects don't know what variables they are assigned to:
# Create three variables referring to an OrderedPair class
tmp = namedtuple('OrderedPair', ['x','y']) # create a new class with metadata
Point = tmp # assign the class to a variable
Coordinate = tmp # assign the class to another var
That's a problem for named tuples. We have to pass in the class name to the namedtuple() factory function so that the class can be given a useful name, docstring, and __repr__ all of which have the class name inside it.
These reason it seems strange to you is that normal function and class definitions are handled differently. Python has special syntax for def
and class
that not only creates functions and classes, but it assigns their metadata (name and docstring) and assigns the result to a variable.
Consider what def
does:
def square(x):
'Return a value times itself'
return x * x
The keyword def
takes care of several things for you (notice that the word "square" will be used twice):
tmp = lambda x: x*x # create a function object
tmp.__name__ = 'square' # assign its metadata
tmp.__doc__ = 'Return a value times itself'
square = tmp # assign the function to a variable
The same is also true for classes. The class
keyword takes care of multiple actions that would otherwise repeat the class name:
class Dog(object):
def bark(self):
return 'Woof!'
The underlying steps repeat the class name (notice that the word "Dog" is used twice):
Dog = type('Dog', (object,), {'bark': lambda self: 'Woof'})
Named tuples don't have the advantage of a special keyword like def
or class
so it has to do the first to steps itself. The final step of assigning to a variable belongs to you. If you think about it, the named tuple way is the norm in Python while def
and class
are the exception:
survey_results = open('survey_results') # is this really a duplication?
company_db = sqlite3.connect('company.db') # is this really a duplication?
www_python_org = urllib.urlopen('http://www.python.org')
radius = property(radius)
You are not the first to notice this. PEP 359 that suggested we add a new keyword, make
, that could allow any callable to gain the auto-assignment capabilities of def
, class
, and import
.
make <callable> <name> <tuple>:
<block>
would be translated into the assignment:
<name> = <callable>("<name>", <tuple>, <namespace>)
In the end, Guido didn't like the "make" proposal because it caused more problems than it solved (after all, it only saves you from making a single variable assignment).
Hope that helps you see why the class name is written twice. It isn't really duplication. The string form of the class name is used to assign metadata when the object is created, and the separate variable assignment just gives you a way to refer to that object. While they are usually the same name, they don't have to be :-)
namedtuple is a factory, returning a class. Consider only expression:
namedtuple(['x','y'])
What would be the name of class returned by this expression?
The class should have a name and know it. And it doesn't see the variable you assign it to, so it can't use that. Plus you could call it something else or even nothing at all:
c = namedtuple('Point', ['x', 'y'])
do_something_with_this(namedtuple('Point', ['x', 'y']))
Speaking of simpler syntax, you can also write it like this:
namedtuple('Point', 'x y')
Because namedtuple
is a function that returns a class. To do that, it is actually rendering a string template and calling eval
. To build the string, it needs all the arguments beforehand.
You need to include the relevant context as arguments to namedtuple
for that to happen. If you don't provide the class name argument, it would need to guess. Programming languages don't like to guess.
With the rules of the Python language, the namedtuple
function within this expression..
>>> Point = namedtuple(['x','y'])
..doesn't have access to variable name (Point
) that the result is stored in once the expression has been executed. It only has access to the elements of the list provided as its argument (and variables that have been defined earlier).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With