Super object has no attribute 'append'
Question: I am working on creating a class for the first time, and I am facing
difficulties here and there, first read my code, and I will post the error
after it

    
    
     import random
    
    class card_deck:
         suites= ["Clubs", "Diamonds", "Hearts", "Spades"]
         ranks= ["Ace", "2", "3", "4", "5", "6", "7", 
                   "8", "9", "10", "Jack", "Queen", "King"]
    def __init__(self, rank, suite, card):
        self.rank= rank
        self.suite = suite
        self.card = card
    def card_list(self):
          suites= ["Clubs", "Diamonds", "Hearts", "Spades"]
          ranks= ["Ace", "2", "3", "4", "5", "6", "7", 
              "8", "9", "10", "Jack", "Queen", "King"]
    def ranks(self):
        return self.rank
    def suite(self):
        return self.suite
    def card(self,card):
        return self.card
    def __str__(self):
        return (Card.ranks[self.rank],
                             Card.suits[self.suit])
    
    
    
    
    def value(self):
        if self.rank == 'Ace':
            return 1
        elif self.rank == 'Jack':
            return 11
        elif self.rank == 'Queen':
            return 12
        elif self.rank == 'King':
            return 13
    def shffule(self):
        random.shuffle(self.card)
    def remove(self,card):
        self.card.remove(card)
    def __getitem__(self,i):
        return self.card_list()
    def append(self,value):
        super(card_deck,self).append(value)
        return self
    
    
    def cardremaining(self):
        self.suite-self.rank
    
    
    
    
     def main():
      try:
          rank = []
          suite = []
          card = []
          deck = card_deck(rank,suite,card)
          deck.shffule()
          #drup=[]
    
    
           for i in ['Spades','Hearts', ' Diamonds','Clubs']:
              for c in ['Ace','2','3','4','5','6','7','8','9','10','Jack','Queen','King']:
                  deck.append([c, i])
    
    
    
          hand = []
          user =eval(input('Enter a number of cards: 1-7 '))
          print()
          while user <1 or user >7:
              print ("Only a number between 1-7:")
              return main()
    
          for i in range(user):
               hand.append(deck[i])
               print(hand)
      except ValueError:
          print("Only numbers")
          main()
    

Here is what I get when I run main()

    
    
      Traceback (most recent call last):
       File "<pyshell#64>", line 1, in <module>
         main() File "/Users/user/Desktop/deck_class.py", line 66, in main
         deck.append([c, i])
       File "/Users/user/Desktop/deck_class.py", line 44, in append
         super(card_deck,self).append(value)
     AttributeError: 'super' object has no attribute 'append'
    

so even if I try to remove super and just write slef.append(value) I get
another error it which python keep printing

    
    
    File "/Users/user/Desktop/deck_class.py", line 44, in append
         card_deck,self.append(value)
       File "/Users/user/Desktop/deck_class.py", line 44, in append
    

I did research before posting the question I tried to fixing it my self, but
it just feels too complicated for me, and I am hoping you guys can help! so
what am i doing wrong?

Thanks


Answer: I'm getting the impression that you're trying to make a `card_deck` object
that is _pretending_ to be a list of some sort. I also feel that you're trying
to make your `card_deck` object act as two separate things: a deck of cards,
and a single card.

Taking that in mind, it would be far simpler to take a step back, split up
your code into two separate classes, and do something like the below. I left
comments in the code to explain my thought process:

    
    
    import random
    
    class Card(object):
        '''Remember, a 'card' is completely different from a deck. You can have a 
        card that is not contained in a deck, and a deck is simply another object
        that contains one or more cards, with a few convenience methods attached.'''
    
        def __init__(self, rank, suite):
            self.rank = rank
            self.suite = suite
    
        def __repr__(self):
            '''The different between '__repr__' and '__str__' is not particularly
            important right now. You can google the difference yourself.'''
            return "Card({0}, {1})".format(self.rank, self.suite)
    
        def __str__(self):
            return "{0} of {1}".format(self.rank, self.suite)
    
        def value(self):
            ranks = ["Ace", "2", "3", "4", "5", "6", "7", 
                "8", "9", "10", "Jack", "Queen", "King"]
    
            # This is something called a 'dictionary comprehension'. It lets you
            # map the rank of the card to its corresponding value. 
            #
            # 'enumerate' is a built-in. Try doing `enumerate(["a", "b", "c", "d"])`
            # in the shell, and see what happens.
            values = {rank: i + 1 for (i, rank) in enumerate(ranks)}
    
            return values[self.rank]
    
    class Deck(object):
        '''Now, we have the deck.'''
    
        def __init__(self):
            self.suites = ["Clubs", "Diamonds", "Hearts", "Spades"]
            self.ranks = ["Ace", "2", "3", "4", "5", "6", "7", 
                 "8", "9", "10", "Jack", "Queen", "King"]
    
            # Here, I've chosen to create a full deck when instantiating the object.
            # You may chose to modify your code to pass in the cards you want instead.
            #
            # Notice how we're keeping track of all of our cards inside of a list.
            # This way, we're free to write whatever methods we want, while still 
            # internally representing our deck of cards in the cleanest manner possible.
    
            self.cards = []
            for suite in self.suites:
                for rank in self.ranks:
                    self.cards.append(Card(suite, rank))
    
        def shuffle(self):
            random.shuffle(self.cards)
    
        def remove(self, card):
            # idk if this will actually work -- you should test it.
            self.cards.remove(card)
    
        def append(self, card):
            '''In this method, we're taking a card, and adding it to our deck.
            We've written the entire thing ourselves -- no need to call to super
            (which doesn't work, in any case)'''
            self.cards.append(card)
    
        def get_top_card(self):
            '''This is a common operation when dealing with decks -- why not add it?'''
            return self.cards.pop()
    
        def __repr__(self):
            return "[" + ", ".join(repr(card) for card in self.cards) + "]"
    
        def __str__(self):
            return '\n'.join(str(card) for card in self.cards)
    
    
    def main():
        deck = Deck()
        deck.shuffle()
    
        hand = []
    
    
        while True:
            user = int(input('Enter a number of cards: 1-7 '))
            print()
            if not 1 <= user <= 7:
                print ("Only a number between 1-7:")
            else:
                break
    
        for i in range(user):
            hand.append(deck.get_top_card())
        print(hand)
    
    if __name__ == '__main__':
        main()
    

Now, you may be wondering what `super(card_deck,self).append(value)` was
actually doing in your original example. Calling `super(card_deck, self)` will
return the **parent class** of the `card_deck` class -- in other words, the
class `card_deck` inherits from.

In this case, your class isn't inheriting anything (technically, it inherits
the built-in "object" class, but every class inherits from `object`, so that's
moot).

Then, when you call `append`, you're trying to call the `append` method that
exists inside the parent class of `card_deck`. However, no such method exists,
so your code throws an exception.

In your case, since you're just beginning to use classes, I would strongly
recommend that you ignore inheritance and the 'super' builtin function for
now. It's overkill, and will only confuse you when you're trying to get a grip
on object-oriented programming. Focus instead on writing good objects that
provide good methods that manipulate variables you define yourself.

