Python Forum
Calling methods and getting results out
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Calling methods and getting results out
#1
Hello again,
I know what I want. I know the algorithm. But I got confused writing my intention in python :(
There are cards, values, colours, complete decks, working print-method - all fine. Also, I know how to shuffle (tested it with a len(10)-list in another playground)

But I got aware, that I dont really understand whats going on in classes, methods and return values. I fumbled a little bit, tried this and that but found no solution. It would be great, if somebody can explain it to me (or showing a link to a site where it's explained) where exactly I got lost...

I tried to copy the output in the comments (line 49-52), hope that is ok? The method seems to be fine, producing no errors (until I try to print the "new" Deck2
There's a text, too. Are these sentences correct and sensible or confused blahblah?




Sincerely & thanks in advance,
HrAyas

''' Creates a Class named "Card" with two attributes:
colour: Kreuz(3), Pik(2), Herz(1), Karo(0)
value: König 13, Dame 12, Bube 11, 10, 9, ..., 2, As (1)

'''
class Card:
    #1st attributs
    colourList = ["Karo", "Herz", "Pik", "Kreuz"]
    valuelist = ["nul", "As", "2", "3", "4", "5", "6", "7", "8", "9", "10", "Bube", "Dame", "König"]
    
    #2nd methods
    
    def __init__(self, colour = 0, value = 1):
        self.colour = colour
        self.value = value

    def __str__(self):
        return f'{self.colourList[self.colour]} {self.valuelist[self.value]}'
    
    
    
'''Now a complete set of 52cards with own methods'''
class Deck:
    '''create with a nested for-loop 4*13 = 52 cards'''
    def __init__(self):
        self.cards = []                                 # empty list---
        for farbe in range(4):
            for rang in range(1,14):
                self.cards.append(Card(farbe, rang))    # --- gets filled
    '''print with a little layout for better overview'''
    def __str__(self):
        s = ""                                          # empty string ---
        for i in range(len(self.cards)):
            s += " "*(i%13) + str(self.cards[i]) + "\n" # --- gets concatenated
        return s
    ''' What about playing with a new deck? SHUFFLE''' 
    def shuffle(self):
        import random
        '''empty list, gets filled with random items from the Deck'''
        mixed = []
        '''append a random item of 'cards' to 'mixed', len()-times'''
        for i in range(len(self.cards)):
            mixed.append(self.cards.pop(random.randint(0,len(self.cards)-1)))
        return mixed

Deck1 = Deck()

#print(Deck1)                                             # works great!
Deck2 = Deck.shuffle(Deck1)     #Create a Deck2, which is the shuffled Deck1... it's doing sth - but what?
'''Sensible and correct?
In the class "Deck" there is a method called "shuffle". 
I call it with the argument "Deck1" 
It is supposed to give me "mixed" (a list?) back. 
I call this returned thing "Deck2". '''

print(Deck2)                    # Result: 52 times <__main__.Card object at 0x0000022769A8BBC0> with different memory locations
Deck2 = Deck1.shuffle           # No error, until "print(Deck2)" is active:
print(Deck2)                    # <bound method Deck.shuffle of <__main__.Deck object at 0x000001C990A8B200>>
Reply
#2
What exactly is the problem?
Was genau ist das Problem?

Deck1 = Deck()
Deck1
<__main__.Deck object at 0x78f2433a7d30>
Deck2 = Deck.shuffle(Deck1)

for card in Deck2:
    print(card)
Gives:
Ergibt:

Output:
Kreuz 7 Kreuz 10 Pik Dame Kreuz 9 Karo Bube Herz Dame Herz As Karo 4 Herz 4 Pik König Pik 4 Kreuz 5 Karo Dame Kreuz 8 Pik 5 Herz 3 Karo 3 Herz 9 Herz 7 Kreuz As Karo 8 Karo 10 Pik 6 Pik 9 Karo 6 Pik 2 Karo 7 Pik 3 Kreuz 3 Karo As Herz 6 Kreuz 4 Pik Bube Karo König Pik 10 Karo 5 Herz König Kreuz 2 Pik As Kreuz Dame Kreuz 6 Herz 2 Karo 9 Kreuz König Karo 2 Herz 10 Herz 8 Herz Bube Pik 8 Kreuz Bube Herz 5 Pik 7
Reply
#3
Deck1 is a Deck object. Deck2 is a method. If you called Deck2 = Deck1.shuffle(), Deck2 would be a list.

If you want to make a copy of a Deck, you need to write a method that makes a new Deck object. I included a copy() method in the Deck code below.
import random  # Imports at the top of the file


class Card:
    colours = ["Karo", "Herz", "Pik", "Kreuz"]
    values = ["nul", "As", "2", "3", "4", "5", "6", "7", "8", "9", "10", "Bube", "Dame", "König"]

    def __init__(self, colour=0, value=1):
        self.colour = colour
        self.value = value

    def __str__(self):
        """Return pretty string."""
        return f'{self.colours[self.colour]} {self.values[self.value]}'


class Deck:
    '''Now a complete set of 52cards with own methods.'''

    def __init__(self, cards=None):
        '''create with a nested for-loop 4*13 = 52 cards.'''
        if cards:
            self.cards = cards.copy()
        else:
            self.cards = [Card(c, v) for c in range(4) for v in range(1, 14)]

    def __str__(self):
        '''Print with a little layout for better overview.'''
        return ", ".join(str(card) for card in self.cards)

    def __len__(self, index=0):
        """Return number of cards in deck."""
        return len(self.cards)

    def copy(self):
        """Return a copy of self."""
        return Deck(self.cards)

    def deal(self, count=1):
        """Return count cards from top of deck."""
        cards = self.cards[:count]
        self.cards = self.cards[count:]
        return cards

    def shuffle(self):
        """Put cards in random order."""
        random.shuffle(self.cards)

    def sort(self, reverse=False):
        """Put cards in sorted order."""
        self.cards.sort(key=lambda c: (c.colour, c.value), reverse=reverse)


deck = Deck()
deck.shuffle()
hands = [Deck(deck.deal(5)) for _ in range(4)]
for i, hand in enumerate(hands, start=1):
    hand.sort()
    print(f"Hand {i}: {hand}")
deck2 = deck.copy()
print("\nShort deck")
print(deck2)
Your code does not follow accepted Python coding conventions. Read about them here:
https://pep8.org/
HerrAyas likes this post
Reply
#4
Hey deanhystad,
thank you very much for this detailed answer. Perhaps you are so kind to spend a little more time:

Some questions, if I got u right:

deck2=Deck() creates an object of class Deck() with the name deck2 ?
deck2 = deck1.shuffle() doesnt copy deck1 in a shuffled state to deck2 ?

Line 22: why do u make this if/else case? It is safer - for what? While in game (only 18cards are left) an calling the __init__ method would overwrite it and create new 52 cards?

Line 31: Why is there an index=0 ? VSCode says "its not accessed by Pylance". Where do you need it?

LIne 45: I wanted to write an own shuffling-method. Do I have logical problems in it? Do I have to have a return value or not?

For the "Python coding conventions": Classes starts with a capital, objects are lowercase?

Thank you so much (even if these questions are too much for you :) for the code and the pep8-link... getting started...

HrAyas
Reply
#5
In your code deck2 = deck1.shuffle() assigns a shuffled list of cards to a variable named "deck2". Doing the same in my code would shuffle the cards in deck1 and assign None to the variable named "deck2". My shuffle() method does not return a value, so the default value of None is returned.
Quote:Line 22: why do u make this if/else case? It is safer - for what?
I wanted my deck to not be limited to 52 cards, so I modified Deck.__init__() to take a list of cards as an argument. If you pass a list of cards, Deck initializes self.cards to be a copy of the list, otherwise it creates a standard 52 card deck.
Quote:While in game (only 18cards are left) an calling the __init__ method would overwrite it and create new 52 cards?
Never call __init__ for an instance. __init__ should only be called automatically one time when the instance is created. The only time your code should call __init__ is when you write a class that is a subclass of another class.
Quote:Line 31: Why is there an index=0 ? VSCode says "its not accessed by Pylance". Where do you need it?
That is a cut and paste error that I didn't catch.
Quote:LIne 45: I wanted to write an own shuffling-method. Do I have logical problems in it? Do I have to have a return value or not?
I assume the "shuffle" you refer to here is your random pick shuffle? Why do you want to do that? One of Python's greatest benefits is how many things Python does with very little effort.

As for having your Deck.shuffle() method return a value or not, that is an application question. Do you think it is logical for shuffle() to return a value? Deck is a deck of cards. shuffle() should shuffle the deck. Does it make sense for shuffle() to create a new deck of shuffled cards? Maybe it does. I could see doing that if I wanted to make a custom deck of cards that I would use as a pattern for making other decks. But even if I was doing that I think it would make more sense to write a copy() method that returns a copy of a deck, and a shuffle method that shuffles the cards in a deck. When your class design lis logical, the code is easy to understand and use.
Quote:For the "Python coding conventions": Classes starts with a capital, objects are lowercase?
Classes are CapWords, starting with a capital and using capital letters to the help readability. variables, functions and methods should use snake_case. All lower case with underscores the help readability. I avoid using extra capitals in class names or underscores in variable or function names.
HerrAyas likes this post
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Search Results Web results Printing the number of days in a given month and year afefDXCTN 1 2,312 Aug-21-2020, 12:20 PM
Last Post: DeaD_EyE
  How to append one function1 results to function2 results SriRajesh 5 3,294 Jan-02-2020, 12:11 PM
Last Post: Killertjuh
  a class calling one of its own methods? Skaperen 1 1,901 Jul-21-2019, 04:43 AM
Last Post: Gribouillis

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020