Can't append a set of values from a Class - python

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

Related

Making multiple objects from user input

This is my current code:
class gym():
def __init__(self,gymname):
self.gymname=gymname
self.memlist=[]
def regMem(self,obj):
if obj.ageMember()==True:
self.memlist.append(obj)
return True, "mem in!!!"
def printMem(self):
for n in self.memlist:
print(n)
class gymMember():
def __init__(self,fname,lname,age):
self.fname=fname
self.lname=lname
self.age=age
def __str__(self):
return(str(self.fname)+str(self.lname)+str(self.age))
def ageMember(self):
if self.age>=18:
return True
def printMemlist(self):
for n in self.memlist:
print(n)
yes='y'
while yes=="y":
g=gym("gym")
name=input('enter f name')
lname=input('enter l name')
age=int(input('enter age'))
n=gymMember(name,lname,age)
print(g.regMem(n))
g.printMem()
I'm trying to create multiple gymMember objects from the user input, but when I print the memlist out with all the gym members, only the most recent gym member appears, not the previous ones. My goal is to take the user input, create gymMember objects, and then store it in the container class gym with the list memlist:
enter f namejosh
enter l namelawmen
enter age23
(True, 'mem in!!!')
joshlawmen23
enter f nametory
enter l nameloome
enter age28
(True, 'mem in!!!')
toryloome28
enter f name
As you can see, only the most recent object shows when I print out the list. How can I fix this?
You had placed g=gym("EzGym") inside the while loop. At every iteration of the while loop, a new instance of gym class is created. When a new instance of gym is created, a new empty list is also created (see line 4: self.memlist=[]).
Therefore, you don't get the previously added gymMember instances when you do a printMem().
You can fix this by shifting g=gym('EzGym') outside of the while loop.
class gym():
def __init__(self,gymname):
self.gymname=gymname
self.memlist=[]
def regMem(self,obj):
if obj.ageMember()==True:
self.memlist.append(obj)
return True, "mem in!!!"
def printMem(self):
for n in self.memlist:
print(n)
class gymMember():
def __init__(self,fname,lname,age):
self.fname=fname
self.lname=lname
self.age=age
def __str__(self):
return(str(self.fname)+str(self.lname)+str(self.age))
def ageMember(self):
if self.age>=18:
return True
def printMemlist(self):
for n in self.memlist:
print(n)
yes='y'
g=gym("EzGym") # shift this line outside of the while loop
while yes=="y":
name=input('enter f name')
lname=input('enter l name')
age=int(input('enter age'))
n=gymMember(name,lname,age)
print(g.regMem(n))
g.printMem()

How to create a new instance using a class method

I am trying to write a method for a class which will create a new instance of an already existing instance of a class. The problem is that I cannot access the new instance in the console when I try new_handname.
This is for creating a blackjack game in python. The idea of the code is when the hand is split a new instance will be created to create a new hand
import random
class Card(object):
def __init__(self, value, suit,nvalue):
self.value = value
self.suit = suit
self.nvalue = nvalue
suit = ['Hearts','Spades','Clubs','Diamonds']
value = ['2','3','4','5','6','7','8','9','10','J','Q','K','A']
nvalue = [2,3,4,5,6,7,8,9,10,10,10,10,11]
class Hand(object):
def __init__(self,current_hand):
self.current_hand = current_hand
def hand_total(self):
current_sum = 0
for i in range(0,len(self.current_hand)):
current_sum += self.current_hand[i].nvalue
return current_sum
def hand_type(self):
if self.current_hand[0].value == self.current_hand[1].value:
return('pair')
elif self.current_hand[0].value == 'A' or self.current_hand[1].value == 'A':
return('soft')
else:
return('hard')
def append(self,current_hand,some_card):
self.current_hand = self.current_hand + some_card
def hit(self):
self.current_hand.append(deck[0])
deck.pop(0)
def double(self,new_handname):
new_handname = Hand(self)
def deal_start_hand():
player_hand.append(deck[0])
deck.pop(0)
dealer_hand.append(deck[0])
deck.pop(0)
player_hand.append(deck[0]) #### player gets two cards ### assuming europe no hole card rules
deck.pop(0)
def gen_deck():
for v,n in zip(value,nvalue):
for s in suit:
deck.append(Card(v,s,n))
### variable initiation ###
deck = []
player_hand = []
dealer_hand = []
##program start ##
gen_deck()
random.shuffle(deck)
deal_start_hand()
p1 = Hand(player_hand)
p1.double('p2')
p2 ### I expect p2 to return an instance but does not
>>> p1
<__main__.Hand object at 0x00000006A80F0898>
>>> p2
Traceback (most recent call last):
File "<pyshell#182>", line 1, in <module>
p2
NameError: name 'p2' is not defined
Note: current_hand is a list of the cards objects.
I expect p2 to return an instance of the class but instead the variable p2 is not defined
Your split routine could look like the following, in which a new instance of the class is returned:
class Hand(object):
def __init__(self, current_hand):
self.current_hand = current_hand
def split(self):
return Hand(self.current_hand)
Simply create an instance, then split it later:
# You need to define "some_default" somewhere
myhand = Hand(some_default)
second_hand = myhand.split()
However, your split routine needs to take into account what cards have already been played, and what cards are still in the deck(s), none of which your code considers. I might advise mapping out the "states" of the game (think of it as a state machine), draw that out on paper, then consider how to code up each state and transition. A card game like this is more complicated to code than it might seem at first glance.

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

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.

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.

Get the return value from a function in a class in Python

I am trying to simply get the value out of my class using a simple function with a return value, I'm sure its a trivial error, but im pretty new to python
I have a simply class set up like this:
class score():
#initialize the score info
def __init__(self):
self.score = 0
self.num_enemies = 5
self.num_lives = 3
# Score Info
def setScore(num):
self.score = num
# Enemy Info
def getEnemies():
return self.num_enemies
# Lives Info
def getLives():
return self.getLives
etc.....
Than I create an instance of the class as such:
scoreObj = score()
for enemies in range(0, scoreObj.getEnemies):
enemy_sprite.add(enemy())
I get the error saying that an integer is expected, but it got an instancemethod
What is the correct way to get this information?
Thanks!
scoreObj.getEnemies is a reference to the method. If you want to call it you need parentheses: scoreObj.getEnemies().
You should think about why you are using a method for this instead of just reading self.num_enemies directly. There is no need for trivial getter/setter methods like this in Python.
The first parameter for a member function in python is a reference back to the Object.
Traditionally you call it "self", but no matter what you call the first parameter, it refers back to the "self" object:
Anytime I get weird errors about the type of a parameter in python, I check to see if I forgot the self param. Been bit by this bug a few times.
class score():
#initialize the score info
def __init__(self):
self.score = 0
self.num_enemies = 5
self.num_lives = 3
# Score Info
def setScore(self, num):
self.score = num
# Enemy Info
def getEnemies(self):
return self.num_enemies
# Lives Info
def getLives(foo): #foo is still the same object as self!!
return foo.num_lives
#Works but don't do this because it is confusing
This code works:
class score():
def __init__(self):
self.score = 0
self.num_enemies = 5
self.num_lives = 3
def setScore(self, num):
self.score = num
def getEnemies(self):
return self.num_enemies
def getLives(self):
return self.getLives
scoreObj = score()
for enemy_num in range(0, scoreObj.getEnemies()):
print enemy_num
# I don't know what enemy_sprite is, but
# I commented it out and just print the enemy_num result.
# enemy_sprite.add(enemy())
Lesson Learned:
Class functions must always take one parameter, self.
That's because when you call a function within the class, you always call it with the class name as the calling object, such as:
scoreObj = score()
scoreObj.getEnemies()
Where x is the class object, which will be passed to getEnemies() as the root object, meaning the first parameter sent to the class.
Secondly, when calling functions within a class (or at all), always end with () since that's the definition of calling something in Python.
Then, ask yourself, "Why am I not fetching 'scoreObj.num_lives' just like so instead? Am I saving processing power?" Do as you choose, but it would go faster if you get the values directly from the class object, unless you want to calculate stuff at the same time. Then your logic makes perfect sense!
You made a simple mistake:
scoreObj.getEnemies()
getEnemies is a function, so call it like any other function scoreObj.getEnemies()

Categories

Resources