6

Why do we need to mention the name Card for namedtuple like below?

import collections

Card = collections.namedtuple('Card', ['rank', 'suit'])

I think a simple Card = collections.namedtuple(['rank', 'suit']) can actually give the same effect right?

For example I can have the same information in a dict like:

card = dict({'rank': 'A', 'suit': 'spade'})

2 Answers 2

6

No, that won't give the same effect.

collections.namedtuple: Returns a new tuple subclass named typename...

namedtuple returns a subclass of the tuple type, not a tuple instance.

The name parameter specifies the class name of the new subclass, just as you would define a regular Python class and give it a name:

>>> from collections import namedtuple
>>> namedtuple('Card', ['rank', 'suit'], verbose=True)
class Card(tuple):
    'Card(rank, suit)'

    __slots__ = ()

    _fields = ('rank', 'suit')

    def __new__(_cls, rank, suit):
        'Create new instance of Card(rank, suit)'
        return _tuple.__new__(_cls, (rank, suit))
    ...

A quick type check clears every doubt:

>>> type(_), issubclass(_, tuple)
(<class 'type'>, True) 

So there, you have namedtuple, a factory function that returns a subclass of a tuple.

Sign up to request clarification or add additional context in comments.

13 Comments

How would you instantiate an anonymous class? Note that a = {} creates a dict instance via the literal, not a dict subclass
Just to complement the very good answer: in practice the creation of the subclass allows things like .__class__ and .__class__.__name__ to work beautifully and as expected. Also a very good and free implementation of __repr__.
@Nishant namedtuple is a function, which returns a new subclass of tuple. <function namedtuple at 0x7f3b4ae7c500>
@Nishant lambda functions are anonymous functions. tuple's name is tuple (class name). A namedtuple's name is the name of the new class returned. It's the design philosophy, else it won't be called named tuple
A more practical question is: Is there any harm in using a "garbage" name? What about 'int'? Or even the empty string ''? For example, Card = namedtuple('int', ['rank', 'suit'], verbose=True)
|
2

When you create a named tuple like this

from collections import namedtuple
Card = namedtuple('Card', ['rank', 'suit'])

You are creating a new class (which is a subclass of tuple)

>>> Card
<class '__main__.Card'>

So for clarity, it is nicer to specifically name the class, as it has it's own specific properties (__init__ takes two arguments, the first becomes the instance's rank attribute, and the second becomes it's suit argument).

The namedtuple author could have used the same name for all of these classes, so it would have looked like <class 'collections.NamedTuple'>. But then how do you tell which one is your new Card class, and which one is your new PokerHands class?

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.