简体   繁体   中英

Python: How to use __add__ special method to add instances of the same class that return another instance of that class

Writing a program for a card game is what motivated the question. Currently, the way I defined the __add__ special method, I can in fact do something like this:

deck_one = Deck()
deck_two = Deck()
decks = deck_one + deck_two  

The challenge is that decks is a list, and I'm curious if there exists a way to add deck_one + deck_two such that decks would instead also become type Deck?

One reason I'm trying to do this, is if I wanted a game to include multiple decks, it would be neat to have the ability to add them all together, and pass them into decks which would 'hold' some n number of decks.

Below is a snippet of my code. I could be completely off here, but would __repr__ play any type of role in this? self.cards is what actually gets referred to in later methods. from what I understand, __repr__ returns it's representation (and as a sideq; I believe __str__ would return the samething if not defined (though please correct me If im wrong), but my understanding is that if I were to only include one, its generally better practice to pick __repr__ , unless both should be included? In anycase:

import collections
import random

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

class Deck:

    values = [str(v) for v in range(2, 11)] + list('JQKA')
    suits = "Spades Diamonds Hearts Clubs".split()

    def __init__(self):
        self.cards = [Card(value, suit) for suit in self.suits for value in self.values]

    def __repr__(self):
        deck_cards = "Deck()\n"
        for card in self.cards:
            deck_cards += f"({card.value}-{card.suit})"
        return deck_cards

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

    def __getitem__(self, position):
        return self.cards[position]

    def __add__(self, deck):
        return self.cards + deck.cards  

    def shuffle(self):
        random.shuffle(self.cards)

    def draw_card(self):
        return self.cards.pop()

The proper approach is maybe to subclass Deck and create a subclass DoubleDeck that has double the number of Cards :

class DoubleDeck(Deck):

    values = Deck.values * 2


len(DoubleDeck())    # --> 104

Implementing the addition operator is a little bit contrived in this case, but can work if you create a new Deck , and concatenate the two lists of Cards from each operand to it, and return it: (This is not my favorite approach to solve the problem)

    def __add__(self, other):
        assert isinstance(other, type(self)
        larger_deck = self.__class__()
        larger_deck.cards = self.cards[:] + other.cards[:]  # making a proper copy of the objects
        return larger_deck

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM