Python Method in a Class - python

I'm trying to start using objects properly, I've built a deck of cards which is my object. I want to be able shuffle and deal cards from it. However I can't figure out how to get the shuffle method to work correctly or even if this is the best way to do it.
import itertools
import random
class Deck:
'''Deck of cards to be used in a card game'''
def __init__(self):
self.faces = ['A', 'K', 'Q', 'J', 'T', '9', '8', '7', '6', '5', '4','3', '2']
self.suits = ['c', 'd', 'h', 's']
self.cards = set(itertools.product(self.faces, self.suits))
def shuffle(self):
self.cards = random.shuffle(self.cards)
def deal(self):
card = self.cards.pop()
return card[0] + card[1]
Usage;
deck = Deck()
deck.shuffle()
deck.deal()

Sets are not ordered, you could use list() to obtain an ordered deck.
Furthermore random.shuffle(l) acts directly on the list and returns None, so you are overwriting the list with None.
import itertools
import random
class Deck:
'''Deck of cards to be used in a card game'''
def __init__(self):
self.faces = ['A', 'K', 'Q', 'J', 'T', '9', '8', '7', '6', '5', '4','3', '2']
self.suits = ['c', 'd', 'h', 's']
self.cards = list(itertools.product(self.faces, self.suits)) # ordered deck
# self.cards = set(itertools.product(self.faces, self.suits)) # unordered deck
def shuffle(self):
random.shuffle(self.cards)
def deal(self):
card = self.cards.pop()
return card[0] + card[1]

Related

Concat method in Class

I am working through the following exercise: I am implementing a class that represents sorted lists of basic types.
Currently:
class SortedList():
def __init__(self, input_list):
self.input_list= input_list
def add(self,value):
self.input_list.append(value)
return self.input_list
def concat(self):
return
def __repr__(self):
self.input_list.sort()
return str(self.input_list)
I make the following calls:
l1= SortedList(['z','l','a'])
print(l1)
l1.add('b')
print(l1)
l2= SortedList(['q','g'])
l3= l1.cocat(l2)
print(l3)
Everything behaves as expected until the l3 definition, since unsure how to define this type of function x.function(y) within a class.
The desired output from the last print statement is ['a','b','g','l','q','z']
You can use the + operator on lists which extends a list with another list, and then return a new instance of SortedList when concat() is called.
class SortedList:
def __init__(self, input_list):
self.input_list = sorted(input_list)
def add(self, value):
self.input_list.append(value)
self.input_list.sort()
return self.input_list
def concat(self, other):
merged = self.input_list + other.input_list
return SortedList(merged)
def __repr__(self):
return str(self.input_list)
l1 = SortedList(["z", "l", "a"])
print(l1)
# ['a', 'l', 'z']
print(l1.add("b"))
# ['a', 'b', 'l', 'z']
l2 = SortedList(["q", "g"])
l3 = l1.concat(l2)
print(l3)
# ['a', 'b', 'g', 'l', 'q', 'z']

Can't stop python from iterating through string in loop

class Hat:
def __init__(self, **kwargs):
self.contents = []
for balltype in kwargs.keys():
for ballnum in range(kwargs[balltype]):
self.contents += balltype
hattrial = Hat(red = 1, blue = 2)
print(hattrial.contents)
I'm trying top create a list that contains the keys from the input argument dictionary, but instead of simply adding the string entry I get:
['r', 'e', 'd', 'b', 'l', 'u', 'e', 'b', 'l', 'u', 'e']
Instead of:
['red', 'blue', 'blue']
Where red occurs once and blue occurs twice. I've tried a few different solutions short of just manipulating the array afterwards such as the attempt below but nothing I've done has changed the output. Surely there's an elegant solution that doesn't require me sticking characters back together?
end = len(balltype)
self.contents += balltype[0:end]
self.contents += balltype
Using append
class Hat:
def __init__(self, **kwargs):
self.contents = []
for balltype in kwargs.keys():
for ballnum in range(kwargs[balltype]):
self.contents.append(balltype)
hattrial = Hat(red = 1, blue = 2)
print(hattrial.contents)
Be careful with the += operator in lists
This also works, try to understand why it appends correctly here with +=
class Hat:
def __init__(self, **kwargs):
self.contents = []
for balltype in kwargs.keys():
self.contents += kwargs[balltype] * [balltype]
hattrial = Hat(red = 1, blue = 2)
print(hattrial.contents)
Basically, the problem with your code can be reduced to the following:
a = []
a += "hello"
a
['h', 'e', 'l', 'l', 'o']

python question about class printing output

class Deck:
def __init__(self):
ranks = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'J', 'Q', 'K', 'A']
suits = ['C', 'D', 'H', 'S']
self.cards = []
for s in suits:
for r in ranks:
self.cards.append(Card(r,s))
def __str__(self):
return str([str(card) for card in self.cards])
def draw(self):
return self.cards.pop()
def shuffle(self):
random.shuffle(self.cards)
def deal(self,n):
deal =[]
for i in range(n):
deal.append(self.cards.pop())
return deal
d=Deck()
print(d.deal(5))
output:
[<__main__.Card object at 0x0000013493F816D0>, <__main__.Card object at 0x0000013493F81100>, <__main__.Card object at 0x0000013493F82160>, <__main__.Card object at 0x0000013493F818B0>, <__main__.Card object at 0x0000013493F6FF40>]
My code prints data information..
I don't know where I did wrong in the code.
Also, is there a way to get a nicer output for deck?
I want my deck to be printed in the shell like this
nice and organized. Thank you in advance
2 C, 3 C, 4 C, 5 C, 6 C,
7 C, 8 C, 9 C, T C, J C,
....
J S, Q S, K S, A S
you can override the card str method like this
import random
class Card:
def __init__(self, r, s):
self.r = r
self.s = s
def __str__(self):
return "{} {}".format(self.r, self.s)
class Deck:
def __init__(self):
ranks = ["2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A"]
suits = ["C", "D", "H", "S"]
self.cards = []
for s in suits:
for r in ranks:
self.cards.append(Card(r, s))
def __str__(self):
return str([str(card) for card in self.cards])
def draw(self):
return self.cards.pop()
def shuffle(self):
random.shuffle(self.cards)
def deal(self, n):
deal = []
for i in range(n):
deal.append(str(self.cards.pop()))
return deal
if __name__ == "__main__":
d = Deck()
print(", ".join(d.deal(5)))

Error in inheriting from parent class PYTHON

class Deck:
def __init__(self):
self.suits = ['S', 'C', 'H', 'D']
self.nums = [2, 3, 4, 5, 6, 7, 8, 9, 10, 'J', 'Q', 'K', 'A']
self.deck = []
def make_deck(self):
self.deck = [f"{j}{i}" for j in self.nums for i in self.suits]
return self.deck
def pop_deck(self):
for i in range(3):
self.deck.pop(0) # gah don't do pop(i), do pop(1)
return self.deck
full_deck = Deck()
print(full_deck.make_deck())
print(full_deck.pop_deck())
class CardDistribution(Deck):
def updated_deck(self):
return self.deck
d = CardDistribution
print(d.updated_deck())
Traceback (most recent call last):
File "/Users/fatimah/PycharmProjects/classes/blackjack.py", line 37, in
print(d.updated_deck())
TypeError: updated_deck() missing 1 required positional argument: 'self'
On-Line 26, You forgot to add () when defining the object.
Updated Code will be:-
class Deck:
def __init__(self):
self.suits = ['S', 'C', 'H', 'D']
self.nums = [2, 3, 4, 5, 6, 7, 8, 9, 10, 'J', 'Q', 'K', 'A']
self.deck = []
def make_deck(self):
self.deck = [f"{j}{i}" for j in self.nums for i in self.suits]
return self.deck
def pop_deck(self):
for i in range(3):
self.deck.pop(0) # gah don't do pop(i), do pop(1)
return self.deck
full_deck = Deck()
print(full_deck.make_deck())
print(full_deck.pop_deck())
class CardDistribution(Deck):
def updated_deck(self):
return self.deck
d = CardDistribution()
print(d.updated_deck())

Can't Get More Cards in Player Hand (Python Blackjack)

I'm learning Python 2 and I'm trying to create a blackjack game using OOP. Can someone please let me know why I can't do hand.hit() twice after running the code below? It only works once. Why?
Also, can someone please let me know how I can calculate the actual value of a player's hand?
Thanks!
import random
rank = ['2', '3', '4', '5', '6', '7', '8', '9', '10', 'Jack', 'Queen', 'King', 'Ace']
suit = ['Diamonds', 'Clubs', 'Hearts', 'Spade']
card_val = {'2':2, '3':3, '4':4, '5':5, '6':6, '7':7, '8':8, '9':9, '10':10, 'Jack':10, 'Queen':10, 'King':10, 'Ace':1}
class Card(object):
def __init__(self, rank, suit):
self.rank = rank
self.suit = suit
def __str__(self):
return str(self.rank) + ' of ' + str(self.suit)
def grab_suit(self):
return self.suit
def grab_rank(self):
return self.rank
def draw(self):
print(self.suit + self.rank)
class Deck(object):
def __init__(self):
self.cards = []
for i in rank:
for j in suit:
self.cards.append(Card(i,j))
def __str__(self):
return str([str(card) for card in self.cards])
def shuffle(self):
random.shuffle(self.cards)
def deal(self):
single_card = self.cards.pop()
return single_card
deck = Deck()
class PlayerHand(object):
def __init__(self):
self.value = []
def __str__(self):
return str([str(card) for card in self.value])
def hit(self):
self.hit = self.value.append(deck.deal())
return self.value
hand = PlayerHand()
Well the answer to the first question is pretty easy: You are overwriting your method with "None" (since self.value.append does not return anything).
So you need to change the line:
self.hit = self.value.append(deck.deal())
To
self.value.append(deck.deal())
Calculating the actual value of the hand has been asked already on stackoverflow, therefore I will only answer the first part of the question.

Categories