Can't make my program generate a random card (1-13) - python

I'm trying to create a class that will have the following:
Class name: Card
Data attributes:
__value
__face_value
Methods:
__init__() – initialize value to 0 and face_value to an empty string
deal() – generates a random card, assigns the value, calls the set_face_value method
set_value() – assigns an integer card value to the value attribute
set_face_value() – sets the face_value based on the what the value attribute is
get_value() – returns the value of the attribute value
get_face_value() – returns the value of the attribute face_value
__str__() – returns the state of the object
This program, will use the "deal" method in my class and will generate a random number, than it will send it to get_face_value to return the face for the card for example: like 2 = Ace, 10 = ten.
This is my program so far:
import random
class Card:
def __init__(self):
self.__value = 0
face_value = {}
def deal(self, get_face_value):
return random.randit(1,13)
def set_value(self):
return self.__value
def get_value(self, find_face_value):
return self.__value
def find_face_value(self):
self.__value = {'1': 'Ace', 'A': 'Ace', 'J': 'Jack', '11': 'Jack', 'Q': 'Queen', '12': 'Queen', 'K': 'King', '13': 'King'}
def __str__(self):
return self.__value
def main():
card = Card()
card.deal()
print (card)
So the idea of this program is that it will generate a random card every time I execute it but I cant seen to figure it out how to put the finish product. What can I do to generate a random card. Here is my error everytime I execute it:
TypeError: deal() missing 1 required positional argument: 'face_value'

Your methods def deal(self, get_face_value) and def get_value(self, find_face_value) require a positional argument (get_face_value and find_face_value respectively). But going by what those methods do, I reckon you don't need them.
In fact, I'm not sure why you would include them there and I suspect the concepts of parameters and arguments are not clear to you.
Additionally, your deal and set_value methods don't seem to do what you probably want them to do. "Getter" methods like your get_value are supposed to return something, but "setter" methods like set_value are supposed to set those values, not return them (or at least not exclusively). With the code you showed us, get_value and set_value do the exact same thing, and deal doesn't set the card's value to the random number you generate, but simply returns that value after generating it (and doing nothing else with it).
Going by your pseudo code, what you want is probably similar to the following:
import random
class Card:
def __init__(self):
self.value = 0
self.face_value = "" # You mention this should be a string. In your example it's an empty dictionary instead.
def deal(self):
self.set_value(random.randint(1, 13) # You originally typoed "randit".
def set_value(self, value):
self.value = value
# Here we set the value attribute and then call the set_face_value.
self.set_face_value()
def set_face_value(self):
# Here we use the card's own value attribute to determine what face value to give it, using a dictionary lookup.
faces = {} # I'll leave compiling the lookup dictionary to you.
# Just notice that the key has to be an integer of the ones you generated above
# in the format 1: "Ace", 2: "Two", 3: "Three" etc.
self.face_value = faces[self.value]
def __str__(self):
return self.face_value
def main():
card = Card()
card.deal()
print(card)
Of course there are many ways to make this code much better but I preferred to keep it both simple and somewhat similar to yours to show you what was wrong with it.

Related

Problem finding array entry based on object attribute

i have been having problems with a function useing an object as an input, but not knowing the position of the object, so i have made a stripped down version of the code to exemplyfi
sett = []
class Test:
def __init__(self, name, number):
self.name = name
self.num = num
#staticmethod
def howmany(who):
print(who.number)
sett.append(Test('dog', 2))
sett.append(Test('cat', 5))
sett.append(Test('fish', 7))
Test.howmany(sett.index(Test.name == 'dog'))
if it worked at intended this would output '2' as that is the number of the object with name 'dog'.
pleas help thanks
Your code has a mix up between num and number. Besides that necessary fix, the index method returns ... an index, not a member of sett. Moreover, Test.name is wrong: Test is your class object, not an instance. You could use the next function to get a matching item.
As a side note: you can just create the list of three items in one go. There is no reason to call append repeatedly:
class Test:
def __init__(self, name, number):
self.name = name
self.number = number # fix
#staticmethod
def howmany(who):
print(who.number)
sett = [Test('dog', 2), Test('cat', 5), Test('fish', 7)]
Test.howmany(next(test for test in sett if test.name == 'dog'))
Another note: it is not clear to me why you want to define howmany as a static method and not as an instance method, unless you would foresee that who could be None, but that logic is currently missing.

Can't append a set of values from a Class

I am doing a card game.
The class is called Card:
It can give a random value with the deal() method to display a random card from the numbers 1-13
The other file will import the file name that contains the Class Card. It will call the class 5 times and be able to store it by appending it on a list and displaying it in another def called display_hand
Here is the class file:
import random
class Card:
def __init__(self):
self.__value = 0
def deal(self):
self.__value = random.randint(1, 13)
def set_value(self, value):
self.__value = value
def get_value(self):
return self.__value
def find_face_value(self):
faces = ['Joker','Ace','Two','Three','Four','Five','Six',
'Seven','Eight','Nine','Ten','Jack','Queen','King']
return faces[self.__value]
def __str__(self):
return self.find_face_value()
The program is too big so this is the def for calling the function 5 times:
def deal_hand():
# Create an empty list to append the cards.
hand = []
deal_hand = classcard3.Card()
for i in range(1, 6):
deal_hand = classcard3.Card()
deal_hand.deal()
# Create a new object in memory and assign it to the
# hand variable
w = classcard3.Card(deal_hand)
# add it to the list
hand.append(w)
return hand
Here is the display function:
def display_hand(hand):
print ("The 5-card hand is: ")
for item in hand:
print(hand)
This is not showing anything except for the print inside the loop. How can I pass it to the display hand to show the cards?
This is the only thing that shows whenever I use the print function inside the loop. I'm trying to use it outside and I have no idea what I'm doing wrong. My apologies if I'm not explaining this too well. I'm a beginner at python and new to this website. Thanks
deal Four
deal Three
deal Five
deal Six
deal Queen
The only error that I'm getting from this is:
line 274, in deal_hand
w = classcard3.Card(deal_hand)
TypeError: __init__() takes 1 positional argument but 2 were given
This doesn't make sense, because I'm doing it just as the book says and is not willing to display the values

Missing parameter error even though parameter is provided

I'm writing a text-based Blackjack game in Python 3.5 and have created the following classes and corresponding methods:
import random
class Card_class(object):
def __init__(self):
pass
def random_card(self):
suites = ['clubs', 'spades', 'diamonds', 'hearts']
denomination = ['ace', 2, 3, 4, 5, 6, 7, 8, 9, 10, 'jack', 'queen', 'king']
card = (suites[random.randint(0, 3)], denomination[random.randint(0, 13)])
return card
def card_check(self, card, cards_distributed):
if card not in cards_distributed:
cards_distributed.append(card)
return True
else:
return False
class Player_hand(object):
def __init__(self):
pass
def cards_held(self, card, cards_holding):
cards_holding.append(card)
return cards_holding
class Distribute_class(object):
def __init_(self):
pass
def initial_card_distribute(self, cards_distributed, player_cards_holding = [], cards_held = 0):
player = ''
while cards_held < 2:
player = Card_class()
result_card = player.random_card()
if not player.card_check(result_card, cards_distributed):
continue
else:
Player_hand.cards_held(result_card, player_cards_holding)
break
return player_cards_holding
I'm attempting to test my code using
distributed_cards = []
player1 = Distribute_class()
player1_hand = player1.initial_card_distribute(distributed_cards)
player1_hand
But I'm given the following error:
TypeError: cards_held() missing 1 required positional argument:
'cards_holding'
The terminal window which presents the error says the error comes from the line containing Player_hand.cards_held(result_card, player_cards_holding) in the final class, Distribute_class, listed above. Does this line not recognize that I had given it a default parameter of player_cards_holding = [] defined in the method within the same class? Or is there some sort of other problem coming from the fact that the method generating the error, "cards_held", is being called from another class?
You are fundamentally misunderstanding how classes work. The problem is that this line:
Player_hand.cards_held(result_card, player_cards_holding)
Is using the instance method cards_held without passing it an instance (which would be self in your method signature). So, to use the method initialize a Player_hand object like so: ph = Player_hand() and then use
ph.cards_held(result_card, player_cards_holding)
What happens under the hood is that ph get's passed implicitly to cards_held.
Also, watch out for the mutable default argument and don't use it unless you understand how it works.
But fundamentally, you are using classes but not correctly. None of your classes have data attributes! All of these could just be module-level functions and work just as well.

Def return in class as second, third argument for Class

I am creating a class to make some calculations. The class would have 3 arguments to get started. I have done like this in a simplified representation:
class TheCalcs:
def __init__(self, pk_from_db, cat_score_list, final_score):
self.pk_from_db = pk_from_db
self.cat_score_list = cat_score_list
self.final_score = final_score
def calculate_cat_score(self):
#Do some calcs with the data of the pk_from_db and return that!
a_list_of_scores = [] # create a list of scores
return a_list_of_scores
def final_score(self): # The argument for this function would be the return of the calculate_cat_score function!
# Again do some calcs and return the final score
the_final_score = int()
return the_final_score
def score_grade(self): # the argument this this function again the return but now from the final_score function
# Do some cals and return the grade
the_grade = ("a string", "an integer")
return the_grade
When I call the class I would have to present the arguments --> However as you can see I just do now the value of the first argument. The second and the third being calculated throughout the class. When I call the class just with one argument I will of course have an error of failing arguments. Anyone has an idea on that?
If those values are calculated, simply don't make them arguments. You could instead call those calculation methods to compute the values:
class TheCalcs:
def __init__(self, pk_from_db):
self.pk_from_db = pk_from_db
self.cat_score_list = self.calculate_cat_score()
self.final_score = self.calculate_final_score()
# ...
or postpone calculations until you need them.

How to intercept a specific tuple lookup in python

I'm wondering how could one create a program to detect the following cases in the code, when comparing a variable to hardcoded values, instead of using enumeration, dynamically?
class AccountType:
BBAN = '000'
IBAN = '001'
UBAN = '002'
LBAN = '003'
I would like the code to report (drop a warning into the log) in the following case:
payee_account_type = self.get_payee_account_type(rc) # '001' for ex.
if payee_account_type in ('001', '002'): # Report on unsafe lookup
print 'okay, but not sure about the codes, man'
To encourage people to use the following approach:
payee_account_type = self.get_payee_account_type(rc)
if payee_account_type in (AccountType.IBAN, AccountType.UBAN):
print 'do this for sure'
Which is much safer.
It's not a problem to verify the == and != checks like below:
if payee_account_type == '001':
print 'codes again'
By wrapping payee_account_type into a class, with the following __eq__ implemented:
class Variant:
def __init__(self, value):
self._value = value
def get_value(self):
return self._value
class AccountType:
BBAN = Variant('000')
IBAN = Variant('001')
UBAN = Variant('002')
LBAN = Variant('003')
class AccountTypeWrapper(object):
def __init__(self, account_type):
self._account_type = account_type
def __eq__(self, other):
if isinstance(other, Variant):
# Safe usage
return self._account_type == other.get_value()
# The value is hardcoded
log.warning('Unsafe comparison. Use proper enumeration object')
return self._account_type == other
But what to do with tuple lookups?
I know, I could create a convention method wrapping the lookup, where the check can be done:
if IbanUtils.account_type_in(account_type, AccountType.IBAN, AccountType.UBAN):
pass
class IbanUtils(object):
def account_type_in(self, account_type, *types_to_check):
for type in types_to_check:
if not isinstance(type, Variant):
log.warning('Unsafe usage')
return account_type in types_to_check
But it's not an option for me, because I have a lot of legacy code I cannot touch, but still need to report on.

Categories

Resources