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'})
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.
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?