How to create a __repr__ of a namedtuple?
Asked Answered
L

3

7

How do I create a special method __repr__ where I can print, for example, '6 of spades' or 'Q of diamonds'?

How do I access the data from the namedtuple, keeping in mind that I have a list of namedtuples in self._cards?

import collections

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

class Deck:
    ranks = [str(n) for n in range (2,11)] + list('JQKA')
    suits = 'spades diamonds hearts clubs'.split()

    def __init__(self):
        self._cards = [cards(rank, suit) for suit in self.suits for rank in self.ranks]

    def __len__(self):
        return len(self._cards)

    def __getitem__(self, item):
        return self._cards[item]

    def __repr__(self):
        return '%s of %s' % ()  # <-- don't know how to assign the string

b = ()
for i in b:
    print(i)
Linnette answered 23/12, 2018 at 0:35 Comment(0)
A
1

It seems like your issue right now is that you are trying to make the __repr__ method inside of your Deck class. That method will only get called when you are trying to print Deck objects, however it seems like you are trying to print a message for a single Card instead. You could solve this by making a simple Card class with suit and rank as class variables, and storing a list of Card objects in your deck. This way you could write a __repr__ method for the card class itself, and reference the card's suit and rank directly.

Appellate answered 23/12, 2018 at 0:45 Comment(0)
S
15

It would be clearer if you renamed cards to Card, since that's the name you assigned to that class:

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

You can extend a namedtuple just like any other class, including to give it __repr__ method. You can even reuse the class name, since a class statement is a type of assignment:

class Card(Card):
    def __repr__(self):
        return f'{self.rank} of {self.suit}'

A more compact version would be

class Card(collections.namedtuple('Card', ['rank', 'suit'])):
    def __repr__(self):
        return f'{self.rank} of {self.suit}'
Seeing answered 23/12, 2018 at 0:46 Comment(0)
B
14

You could use typing.NamedTuple instead, which allows you to define methods normally:

from typing import NamedTuple

class Card(NamedTuple):
    rank: str
    suit: str
    def __repr__(self):
        return "{} of {}".format(self.rank, self.suit)
Bridgetbridgetown answered 23/12, 2018 at 0:50 Comment(0)
A
1

It seems like your issue right now is that you are trying to make the __repr__ method inside of your Deck class. That method will only get called when you are trying to print Deck objects, however it seems like you are trying to print a message for a single Card instead. You could solve this by making a simple Card class with suit and rank as class variables, and storing a list of Card objects in your deck. This way you could write a __repr__ method for the card class itself, and reference the card's suit and rank directly.

Appellate answered 23/12, 2018 at 0:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.