Connecting and changing .txt-values to/from a mainfunction - python

I'm trying to create a class with private attributes (the attributevalues are imported from a .txt-file) the user should be able to change the values of the attribute. The list looks like this:
Rats
Berta/2/4/3/0
Oscar/5/0/3/2
John/-1/-6/-5/-9
My question is; where does my messy code go wrong? What am I missing? I've been searching the web for answers for a few days now.
#The class
class Rat(object):
"""Defines my class"""
def __init__(self, rat_name, sleep, joy, full, happiness):
self.__rat_name = rat_name
self.__sleep = sleep
self.__joy = joy
self.__full = full
self.__happiness = happiness
def setfull(self, value, absolute = False):
"""Gives the full attribute a value"""
try:
value = int(value)
if absolute:
self.__full = value
else:
self.__full += value
return True
except ValueError:
return False
def getfull(self):
"""Gives a fullvalue"""
return self.__full
def setfull(self, x):
x = int(x)
"""acess to the full attribute"""
self.__full = x
def sethappiness(self, value, absolute = False):
"""Gives the happiness attribute a value"""
try:
value = int(value)
if absolute:
self.__happiness = value
else:
self.__happiness += value
return True
except ValueError:
return False
def gethappiness(self):
"""Gives happiness value"""
return self.__happiness
def sethappiness(self, x):
"""access to the happiness attribute"""
x = int(x)
self.__happiness = x
def setsleep(self, value, absolute = False):
"""Gives the sleep attribute a value"""
try:
value = int(value)
if absolute:
self.__sleep = value
else:
self.__sleep += value
return True
except ValueError:
return False
def getsleep(self):
"""Gives a sleep value"""
return self.__sleep
def setsleep(self, x):
"""access to the sleep attribute"""
x = int(x)
self.__sleep = x
def setjoy(self, value, absolute = False):
"""Gives a value to the joy attribute"""
try:
value = int(value)
if absolute:
self.__joy = value
else:
self.__joy += value
return True
except ValueError:
return False
def getjoy(self):
"""Gives a joy value"""
return self.__joy
def setjoy(self, x):
"""access to the joy attribute"""
x = int(x)
self.__joy = x
# main menu functions
def cheese(self):
"""Feeds the pet"""
print("- Mmmm cheese!")
self.__full += 3
self.__sleep += 1
self.__joy += 1
return self.__full, self.__sleep, self.__joy
def play(self):
"""Plays with the rat"""
print("- Oh, I'm having fun!")
self.__full -= 2
self.__sleep += 2
self.__joy += 4
self.__happiness += 2
return self.__full, self.__sleep, self.__joy, self.__happiness
def tosleep(self):
"""Let the rat sleep"""
print("Zzzzzzz")
self.__sleep -= 7
self.__joy += 1
return self.__sleep, self.__joy
def trap(self):
"""A mousetrap"""
if self.__full > 5:
print("The rat is to full to be fooled by a simple mousetrap")
else:
print("The rat escaped with a broken tail!")
self.__joy -= 2
self.__happiness -=2
return self.__full, self.__sleep, self.__joy, self.__happiness
def __str__(self):
"""Returns a string that describes the mood of the rat"""
mood =self.rat_name + " är: "
if self.__joy > 5:
mood += "Glad, "
else:
mood += "Pissed, "
if self.__full > 8:
mood += "overfed, "
elif self.__full > 0:
mood += "full, "
elif self.__full < -5:
mood += "starving, "
else:
mood += "craving cheese and "
if self.__sleep > 7:
mood += "very tired and "
elif self.__sleep > 0:
mood += "sleepy and "
else:
mood += "well rested and "
if self.__happiness > 7:
mood += "SUPER HAPPY!"
elif self.__happiness > 0:
mood += "quite happy!"
else:
mood += "unhappy..."
return mood
# The list
def listan():
"""Opens and sorts the list"""
infil = open("ratlist.txt", "r")
infil.readline
rats = []
for row in infil:
lista = row.split("/")
print(lista)
ratname = lista[0]
ratsleep = int(lista[1])
ratjoy = int(lista[2])
ratfull = int(lista[3])
rathappiness = int(lista[4].strip())
t = Rat(ratname, ratsleep, ratjoy, ratfull, rathappiness)
rats.append(t)
print("Finished")
return rats
# the main menu
def main():
"""The menu"""
ratzinger = listan()
choice = None
while choice != "1":
print \
("""
The ratkeeper
1 - Buy a cat
2 - Listen to your rat
3 - Let the rat sleep
4 - Give the rat cheese
5 - Prepare a mousetrap
6 - Play with the rat
7 - Change the values of your rat
8 - Know the name of my rat
""")
choice = input("I want to: ")
if val == "1":
print(rat_name, "was tortured and eaten, bye.")
elif val == "2":
print(ratzinger)
elif val == "3":
ratzinger.tosleep()
elif val == "4":
ratzinger.cheese()
elif val == "5":
ratzinger.trap()
elif val == "6":
ratzinger.play()
elif val == "7":
print()
elif val == "8":
print()
else:
print("Choose a number between one and eight!")
main()
input()

In addition to the answer above: double underscores in Python do not imply that the marked attribute is private. Double underscores apply name mangling and are used to avoid naming-collisions. If you mean "private" then you should use a single underscore.

Related

CS50 Introduction to Programming with Python: Problem with Check50 in PSet4

I'm taking CS50 Introduction to Programming with Python. I have problem with PSet4 (Little Professor). I don't have any problem while running, but when check50 running it keeps giving this error: "Little Professor accepts valid level timed out while waiting for program to exit." While I’m manually running the program, it accepts any level value lower than 4. But the check50 says otherwise. Here is my code:
import random
def main():
try:
level = input("Level: ")
first, second = get_level(level)
game_on(first, second, 0, 2, 0, level)
except WrongInputError:
main()
def get_level(x):
try:
x = int(x)
if 0 < x < 4:
first = generate_integer(x)
second = generate_integer(x)
return first, second
else:
raise WrongInputError
except ValueError:
raise WrongInputError
class WrongInputError(Exception):
"""You entered something wrong, try again """
def generate_integer(level):
if level == 1:
integer = random.randrange(10)
return integer
elif level == 2:
x = str(random.randrange(1, 10))
y = str(random.randrange(10))
integer = int(x + y)
return integer
elif level == 3:
x = str(random.randrange(1, 10))
y = str(random.randrange(10))
z = str(random.randrange(10))
integer = int(x + y + z)
return integer
def game_on(x , y, count, lives, score, level):
game_set = [x, y]
try:
if count < 10:
calculation = int(input(f"{x} + {y} = "))
count += 1
if calculation == sum(game_set):
score +=1
first, second = get_level(level)
game_on(first, second, count, 3, score, level)
elif calculation == sum(game_set):
print("EEE")
if lives > 0:
lives -= 1
count -= 1
game_on(x, y, count, lives, score, level)
elif lives == 0:
print(f"{x} + {y} = {sum(game_set)}")
first, second = get_level(level)
game_on(first, second, count, 2, score, level)
else:
print(f"Score: {score}")
except ValueError:
print("EEE")
if lives > 0:
lives -= 1
game_on(x, y, count, lives, score, level)
elif lives == 0:
print(f"{x} + {y} = {sum(game_set)}")
first, second = get_level(level)
game_on(first, second, count, 2, score, level)
if __name__ == "__main__":
main()
main()
import sys
import random
def main():
num = get_level()
errors = 1
score = 0
for i in range(10):
x = generate_integer(num)
for j in range(1):
y = generate_integer(num)
answer = x + y
equation = input(f"{x} + {y} = ")
if int(equation) == answer:
score += 1
while int(equation) != answer:
errors += 1
print("EEE")
equation = input(f"{x} + {y} = ")
if errors >= 3:
print(answer)
sys.exit("Score: " + str(score))
print("Score: " + str(score))
# prompt for level and reprompt if needed
def get_level():
levelChoice = input("Level: ")
if levelChoice.isalpha() or int(levelChoice) <= 0 or int(levelChoice) > 3:
input("Level: ")
else:
levelChoice = int(levelChoice)
for i in [1,2,3]:
if levelChoice == i:
return levelChoice
# generate int from level choice
def generate_integer(level):
try:
if level == 1:
return random.randint(0, 9)
elif level == 2:
return random.randint(10, 99)
elif level == 3:
return random.randint(100, 999)
except:
raise ValueError
if __name__ == "__main__":
main()

List has no items to pop however there was something there?

Trying to make a brainfuck interpreter in python from scratch just for fun, I'm almost done with the code however this small error is coming up whenever I try interpreting ",[>++++<]" Which is supposed to input a number, and multiply it by 4. It stops and gets this error
File ".\bfInterpreter.py", line 42, in endWhile
if self.stack[self.pointer]: self.place = self.inWhile.pop(-1)
IndexError: pop from empty list
Any ideas?
here is the code that the error is in:
import sys
import time
class Operator:
def __init__(self) -> None:
self.pointer = 0
self.place = 0
self.inWhile = []
self.stack = [0]
def plus(self):
self.stack[self.pointer]+=1
def minus(self):
self.stack[self.pointer]-=1
def left(self):
if self.pointer > 0: self.pointer -= 1
else: raise IndexError
def right(self):
self.pointer += 1
try: self.stack[self.pointer] = 0
except: self.stack.append(0)
def output(self):
print(ascii(self.stack[self.pointer]))
def inp(self):
val = input("Num: ")
try: self.stack[self.pointer] = int(val)
except:
print("Please input a number")
self.inp()
def startWhile(self):
self.inWhile.append(self.place)
print(self.inWhile)
def endWhile(self):
print(self.inWhile)
if self.stack[self.pointer]: self.place = self.inWhile.pop(-1)
def interpret(self, bf):
self.place = 0
while self.place < len(bf):
if bf[self.place] == "+": self.plus()
elif bf[self.place] == "-": self.minus()
elif bf[self.place] == "<": self.left()
elif bf[self.place] == ">": self.right()
elif bf[self.place] == "[": self.startWhile(bf)
elif bf[self.place] == "]": self.endWhile()
elif bf[self.place] == ",": self.inp()
elif bf[self.place] == ".": self.output()
else: raise SyntaxError
self.place += 1
print(self.stack)
def main():
start = time.time()
op = Operator()
op.interpret(",[>++++<]")
print(f"Ended in {time.time() - start} second(s)")
if __name__ == "__main__": main()
Edit: self.stack is basically the memory that brainfuck is allowed to access and edit, so the "[" starts a while loop, checking if a certain spot in the stack has reached 0 every cycle, and if it's not 0, it repeats the code in the brackets
The main problem is self.inWhile.pop(-1) in command ] - it removes value from list and in next loop this list is empty - so pop(-1) raises your error message.
But there is more mistakes and problems in [ and ].
All commands runs self.place += 1 but ] shouldn't do this because this way it jump to first command after [ but it should run again [. Maybe if it would run again [ then it could add again value to inWhile and self.inWhile.pop(-1) whouldn't make problem.
But there is other problem with [ - it should check if value is 0 and jump to first command after ]. It would need another list to remember position of ] but it seems more complicated - because if at start value is 0 then it couldn't yet run ] and it couldn't add position to list. Better is to search matching ] in string with commands. The same method I used to search [ (instead of using inWhile).
Other problem is > you always try to set stack[place] = 0 but if you run > and next < and again > then stack[place] may already exists and it may have some value and stack[place] = 0 may remove this value. I rather use while loop with pointer >= len(stack) to append values only if stack is really too short.
Other problem is that program in branfuck runs loop forever because it doesn't have - to decreate inputed value. It needs also >. after loop to display result.
,[->++++<]>.
My version without inWhile but with loop which search matching [ or matching ].
import sys
import time
class Operator:
def __init__(self):
self.place = 0 # command place
self.pointer = 0 # stack pointer
self.stack = [0]
def input(self):
#print('[DEBUG] input')
while True:
val = input("Number: ")
try:
self.stack[self.pointer] = int(val)
break
except:
print("Please input a integer number")
def output(self):
#print('[DEBUG] output')
print(ascii(self.stack[self.pointer]))
def plus(self):
#print('[DEBUG] plus')
self.stack[self.pointer] += 1
def minus(self):
#print('[DEBUG] minus')
self.stack[self.pointer] -= 1
def left(self):
#print('[DEBUG] left')
if self.pointer > 0:
self.pointer -= 1
else:
raise IndexError
def right(self):
#print('[DEBUG] right')
self.pointer += 1
while len(self.stack) <= self.pointer:
self.stack.append(0)
def start_loop(self):
#print('[DEBUG] start_loop')
#print('self.place:', self.place)
if self.stack[self.pointer] == 0:
# find matching `]` to jump to next command after `]`
counter = 1
while counter > 0:
self.place += 1
char = self.bf[self.place]
if char == '[':
counter += 1
elif char == ']':
counter -= 1
#print('counter:', counter)
def end_loop(self):
#print('[DEBUG] end_loop')
#print('self.place:', self.place)
# find matching `[` to run again `[` and all loop
counter = 1
while counter > 0:
self.place -= 1
char = self.bf[self.place]
if char == '[':
counter -= 1
elif char == ']':
counter += 1
#print('counter:', counter)
def interpret(self, bf):
self.bf = bf
self.place = 0
while self.place < len(bf):
char = self.bf[self.place]
#print('[DEBUG] interpret:', self.place, bf[self.place])
if char == ",":
self.input()
self.place += 1
elif char == ".":
self.output()
self.place += 1
elif char == "+":
self.plus()
self.place += 1
elif char == "-":
self.minus()
self.place += 1
elif char == "<":
self.left()
self.place += 1
elif char == ">":
self.right()
self.place += 1
elif char == "[":
self.start_loop()
self.place += 1
elif char == "]":
self.end_loop()
# it has to be without `self.place += 1`
else:
raise SyntaxError
print('stack:', self.stack)
def main():
start = time.time()
op = Operator()
op.interpret(",[->++++<]>.") # input*4
#op.interpret(",[->+>++>+++>++++<<<<]>.>.>.>.") # input*1, input*2, input*3, input*4
#op.interpret(",[->+<>>++<<>>>+++<<<>>>>++++<<<<]>.>.>.>.") # input*1, input*2, input*3, input*4
end = time.time()
print(f"Ended in {end - start:.2f} second(s)")
if __name__ == "__main__":
main()

TypeErr: Object "int" is not callable

I tried to make a "typing game" and at first, it worked out pretty nice. But when I translated my code to English (variable names, class names, function names etc.) it gave me the warning "Object int is not callable". How can I solve this?
Here's my code:
import time
import random
import sys
class Player():
def __init__(self, name, health = 5, energy = 10):
self.name = name
self.health = health
self.energy = energy
self.hit = 0
def inf(self):
print("Health: ", self.health, "\nEnergy: ", self.energy, "\nName: ", self.name)
def attack(self, opponent):
print("Attacking")
time.sleep(.300)
for i in range(3):
print(".", end=" ", flush=True)
x = self.randomAttack()
if x == 0:
print("Nobody attacks.")
elif x == 1:
print("{} hits {} !".format(name, opponentName))
self.hit(opponent)
opponent.health -= 1
elif x == 2:
print("{} hits {}!".format(opponentName, name))
opponent.hit(self)
self.health -= 1
def randomAttack(self):
return random.randint(0, 2)
def hit(self, hit):
hit.hitVariable += 1
hit.energy -= 1
if (hit.hitVariable % 5) == 0:
hit.health -= 1
if hit.health < 1:
hit.energy = 0
print('{} won the game!'.format(self.name))
self.exit()
#classmethod
def exit(cls):
sys.exit()
def run(self):
print("Running...")
time.sleep(.300)
print("Opponent catch you!")
#######################################################
print("Welcome!\n----------")
name = input("What's your name?\n>>>")
opponentName = input("What's your opponent's name?\n>>>")
you = Player(name)
opponent = Player(opponentName)
print("Commands: \nAttack: a\nRun: r\nInformation: i\nExit: e")
while True:
x = input(">>>")
if x == "a":
you.attack(opponent)
elif x == "r":
you.run()
elif x == "i":
you.inf()
elif x == "e":
Player.exit()
break
else:
print("Command not found!")
continue
It gives me the error at line 24 (self.hit(opponent)).
Your hit function is the problem. You have member and a function with the same name. Change one of them.
Also rename the hit argument of the hit(). You call it via self.hit(opponent) so I would rename it to def hit(self, opponent):.
def __init__(self, name, health = 5, energy = 10):
self.hit = 0
def hit(self, hit):
hit.hitVariable += 1
hit.energy -= 1
if (hit.hitVariable % 5) == 0:
hit.health -= 1
if hit.health < 1:
hit.energy = 0
print('{} won the game!'.format(self.name))
self.exit()

Python 2.7.10 AttributeError

I have the following code and cant seem to realized why I get this error: Traceback (most recent call last):
card_ranks = [c.rank for c in cards[i:i+5]]
AttributeError: 'str' object has no attribute 'rank'
Here's the code:
import random
import logging
from collections import OrderedDict
from const import __version__, suits, ranks, POS_TOP, POS_BOTTOM
logger = logging.getLogger(__name__)
def f_list(lst, sep=','):
return sep.join([str(x) for x in lst])
def f_lists(lst, sep=' / '):
return f_list(map(f_list, lst), sep)
class Card(object):
"""Represents a single french-design card with it's rank and suit.
Cards can be compared and ordered by rank. A card, relative to
a card of the same rank but different suit, is compared as neither
higher, lower nor equal.
:param rank: Either the rank (one of 'A', 'K', 'Q', 'J', 'T', '9', ... '2')
or rank and suit together (e.g. 'AS', '8H', etc.)
:type rank: str
:param suit: The suit, if not given as one string with rank
(one of 'S', 'H', 'C', 'D' for spade, heart, club or diamond)
:type suit: str
:raises: ValueError
"""
def __init__(self, rank, suit=None):
if suit is None:
suit = rank[1]
rank = rank[0]
if rank not in ranks:
raise ValueError('Card(): Invalid rank')
if suit not in suits:
raise ValueError('Card(): Invalid suit')
self.rank = rank
self.suit = suit
#classmethod
def card_list(cls, *args):
"""Create a list of new cards.
Each argument should describe one card with rank and suit together.
:param args: One or more cards.
:type rank: str
:returns: List of new cards, one for each input parameter.
:rtype: list of :class:`pokercards.cards.Card` objects
:raises: ValueError
"""
lst = []
for c in args:
lst.append(cls(c))
return lst
def __str__(self):
return self.rank + self.suit
def __repr__(self):
return 'Card(%s, %s)' % (self.rank, self.suit)
def __hash__(self):
return (ord(self.rank) << 8) + ord(self.suit)
def __eq__(self, obj):
return self.rank == obj.rank and self.suit == obj.suit
def __ne__(self, obj):
return self.rank != obj.rank or self.suit != obj.suit
def __lt__(self, obj):
return ranks.index(self.rank) > ranks.index(obj.rank)
def __gt__(self, obj):
return ranks.index(self.rank) < ranks.index(obj.rank)
def __le__(self, obj):
return ranks.index(self.rank) >= ranks.index(obj.rank)
def __ge__(self, obj):
return ranks.index(self.rank) <= ranks.index(obj.rank)
class Deck(object):
"""Represents a single deck of 52 :class:`card.Card` objects.
The deck could be imagined face down on a table. All internal lists
represent the cards in order from bottom up. So dealing the top
card means poping last item from the list.
"""
def __init__(self):
self.popped = []
self.discarded = []
self.active = []
for s in suits:
for r in ranks:
self.active.append(Card(r, s))
def shuffle(self):
"""Shuffle the deck."""
random.shuffle(self.active)
def pop(self):
"""Deal the top card from the deck.
:returns: :class:`pokercards.cards.Card` instance
"""
card = self.active.pop()
self.popped.append(card)
return card
def discard(self):
card = self.active.pop()
self.discarded.append(card)
def return_cards(self, cards, pos = POS_BOTTOM):
if pos not in (POS_BOTTOM, POS_TOP):
raise Exception('Deck.return_cards(): invalid pos parameter')
for card in cards[:]:
if card in self.discarded:
self.discarded.remove(card)
elif card in self.popped:
self.popped.remove(card)
else:
raise Exception('Deck.return_cards(): card not among removed cards')
if pos == POS_BOTTOM:
self.active[0:0] = [card]
else:
self.active.append(card)
def return_discarded(self, pos = POS_BOTTOM):
self.return_cards(self.discarded, pos)
def return_popped(self, pos = POS_BOTTOM):
self.return_cards(self.popped, pos)
def return_all(self, pos = POS_BOTTOM):
self.return_popped()
self.return_discarded()
def stats(self):
return (len(self.active), len(self.popped), len(self.discarded))
def __str__(self):
return '[%s]' % ' '.join((str(card) for card in self.active))
def __repr__(self):
return 'Deck(%s)' % self.__str__()
class PokerHand(object):
"""Compute the best hand from given cards, implementing traditional
"high" poker hand ranks.
The hand object can be given more than five cards (as in Texas
Hold'em or similar variants) and the evaluation will pick the best
hand.
Evaluated :class:`pokercards.cards.PokerHand` objects are
compared and sorted by the rank of the hand.
.. attribute:: cards
List of :class:`pokercards.cards.Card` objects to make the hand
from. The :meth:`pokercards.cards.PokerHand.evaluate` method
should be called after manual update to re-evaluate the updated
hand.
Following attributes are available after evaluating the hand.
.. attribute:: hand_rank
Readonly rank of the hand (0 = high card to 8 = straight flush)
.. attribute:: hand_cards
Readonly list of cards which complete the rank.
.. attribute:: kickers
Readonly list of extra cards which can break a tie.
:param cards: List of :class:`pokercards.cards.Card` objects.
:param evaluate: Evaluate the hand when creating.
:type evaluate: bool
"""
def __init__(self, cards, evaluate=True):
cards.sort(reverse=True)
self.cards = cards
if evaluate:
self.evaluate()
def evaluate(self):
"""Evaluate the rank of the hand.
Should be called either implicitly at start by leaving
parameter ``evaluate`` True when creating the hand or
explicitly by calling this method later, e.g. after changing
the :attr:`cards` attribute manually.
"""
self._eval_hand_rank()
self._fill_kickers()
def _by_rank(self, cards=None):
if cards is None:
cards = self.cards
ranked = OrderedDict()
for card in cards:
if card.rank in ranked:
ranked[card.rank].append(card)
else:
ranked[card.rank] = [card]
return ranked
def _by_suit(self, cards=None):
if cards is None:
cards = self.cards
suited = OrderedDict()
for card in cards:
if card.suit in suited:
suited[card.suit].append(card)
else:
suited[card.suit] = [card]
return suited
def _find_flushes(self, cards=None):
if cards is None:
cards = self.cards
flushes = []
for cards in self._by_suit(cards).values():
l = len(cards)
if l >= 5:
for i in xrange(0, l - 4):
flushes.append(cards[i:i+5])
return flushes
def _find_straights(self, cards=None):
if cards is None:
cards = self.cards
straights = []
for i in xrange(0, len(cards) - 4):
card_ranks = [c.rank for c in cards[i:i+5]]
j = ranks.index(card_ranks[0])
if card_ranks == ranks[j:j+5]:
straights.append(cards[i:i+5])
return straights
def _fill_kickers(self):
hand_count = len(self.hand_cards)
kicker_count = 5 - hand_count
if kicker_count > 0:
kickers = self.cards[:]
for card in self.hand_cards:
kickers.remove(card)
self.kickers = kickers[:kicker_count]
else:
self.kickers = []
logger.debug("kickers: %s", f_list(self.kickers))
logger.debug("--- -------------- ---")
def _eval_hand_rank(self):
logger.debug("--- Evaluating %s ---", f_list(self.cards))
straights = self._find_straights()
if straights: logger.debug( "straights: %s", f_lists(straights))
flushes = self._find_flushes()
if flushes: logger.debug("flushes: %s", f_lists(flushes))
pairs = []
threes = []
fours = []
for cards in self._by_rank().values():
l = len(cards)
if l >= 4:
fours.append(cards[0:4])
elif l == 3:
threes.append(cards)
elif l == 2:
pairs.append(cards)
if pairs: logger.debug("pairs: %s", f_lists(pairs))
if threes: logger.debug("threes: %s", f_lists(threes))
if fours: logger.debug("fours: %s", f_lists(fours))
# straight flush
for cards in straights:
if cards in flushes:
self.hand_rank = 8
self.hand_cards = cards
logger.debug("* straight flush: %s", f_list(self.hand_cards))
return
# four of a kind
if len(fours) > 0:
self.hand_rank = 7
self.hand_cards = fours[0]
logger.debug("* four of a kind: %s", f_list(self.hand_cards))
return
# full house
if len(threes) > 1:
self.hand_rank = 6
self.hand_cards = threes[0] + threes[1][:2]
logger.debug("* full house: %s", f_list(self.hand_cards))
return
elif len(threes) == 1 and len(pairs) > 0:
self.hand_rank = 6
self.hand_cards = threes[0] + pairs[0]
logger.debug("* full house: %s", f_list(self.hand_cards))
return
# flush
if len(flushes) > 0:
self.hand_rank = 5
self.hand_cards = flushes[0]
logger.debug("* flush: %s", f_list(self.hand_cards))
return
# straight
if len(straights) > 0:
self.hand_rank = 4
self.hand_cards = straights[0]
logger.debug("* straight: %s", f_list(self.hand_cards))
return
# three of a kind
if len(threes) > 0:
self.hand_rank = 3
self.hand_cards = threes[0]
logger.debug("* three of a kind: %s", f_list(self.hand_cards))
return
# two pair
if len(pairs) > 1:
self.hand_rank = 2
self.hand_cards = pairs[0] + pairs[1]
logger.debug("* two pairs: %s", f_list(self.hand_cards))
return
# one pair
if len(pairs) == 1:
self.hand_rank = 1
self.hand_cards = pairs[0];
logger.debug("* two of a kind: %s", f_list(self.hand_cards))
return
# high card
self.hand_rank = 0
self.hand_cards = [self.cards[0]]
logger.debug("* high card: %s", f_list(self.hand_cards))
def __str__(self):
return '[%s]' % f_list(self.cards)
def __repr__(self):
return '%s(%s)' % (self.__class__.__name__, self.__str__())
def __cmp__(self, other):
if self.hand_rank > other.hand_rank:
return 1
elif self.hand_rank < other.hand_rank:
return -1
else:
# same rank
for c1, c2 in zip(self.hand_cards, other.hand_cards):
if c1 > c2:
return 1
elif c1 < c2:
return -1
else:
# same cards, check kickers
for c1, c2 in zip(self.kickers, other.kickers):
if c1 > c2:
return 1
elif c1 < c2:
return -1
# really, a tie
return 0
deck = Deck()
deck.shuffle()
player = []
computer = []
cmoney = 500
money = 500
pot = 0
for i in range(5):
card = deck.pop()
player.append(str(card))
player.sort()
for i in range(5):
card = deck.pop()
computer.append(str(card))
computer.sort()
pot += 10
money -= 5
cmoney -= 5
print "All players have anted $5."
print "Your Hand:", player
print "Your Money: $" + str(money)
print "Pot: $" + str(pot)
discard = []
ask = raw_input("Bet or check? ")
if ask.lower() == "bet":
ask2 = int(raw_input("How much? "))
if ask2 > money:
print "You don't have that much money!"
else:
money -= ask2
cmoney -= ask2
pot += ask2 * 2
print("Pot: $" + str(pot))
ui = raw_input("Do you want to discard some cards? ")
if ui.lower() == "yes":
ui2 = int(raw_input("How many? "))
for i in range(ui2):
ui3 = raw_input("Card " + str(i + 1) + ": ")
discard.append(ui3)
player.pop()
for i in range(ui2):
card = deck.pop()
player.append(str(card))
print "Your Hand:", player
print "Your Money: $" + str(money)
ask3 = raw_input("Bet or check? ")
if ask3.lower() == "bet":
ask4 = int(raw_input("How much? "))
if ask4 > money:
print "You don't have that much money!"
else:
money -= ask4
pot += ask4
pval = PokerHand(player, True)
cval = PokerHand(computer, True)
if pval > cval:
print "YOU WIN!"
money += pot
pot = 0
else:
print "YOU LOSE!"
cmoney += pot
pot = 0
print "Pot: $" + str(pot)
print "Your Hand:", player
print "Computer\'s Hand:", computer
You are constructing the PokerHand with an array of strings, not an array of cards. The code is here:
for i in range(5):
card = deck.pop()
player.append(str(card))
player.sort()
for i in range(5):
card = deck.pop()
computer.append(str(card))
computer.sort()
Instead of str(card), try just using append(card). Hopefully that should work, unless you use the string elsewhere.

How do I make an elif command which occurs in a for loop only register for certain instances of an item within the list?

Below is part of my code. Basically what this does is when run it creates credit cards with a random number and a given currency code and credit card limit. The Credit Card is a class and the money it stores is also a class (Which I have not included here for brevity and because I think they are not relevant to my question.) What happens in my code, however, is that my cancel statement works out fine but if I have two credit cards in a list and I try to cancel the second one it will again print out NO_SUCH_CARD. The card gets deleted anyway if its in the list. My guess is that his happens because the for loop iterates through the list and it first detects a card whose number is different than the given one, which is why it prints no such card, but I have no idea how to fix this. Help would be appreciated.
PATH = 'saved_cards.txt'
creditcard_list = []
import decimal
import ast
import collections
import os
import random
def currency_dictionary():
'''Initialized at the start of the program. It finds and reads a currency.txt
file and stores those in a dictionary'''
final_dict = collections.defaultdict(list)
with open("currency.txt", 'r') as f:
currency_lines = f.readlines()
for item in currency_lines:
m = item.split(' ')
final_dict[m[0]] = [int(m[1]), decimal.Decimal(m[2])]
return final_dict
class Money():
def __init__(self, money_amount: decimal, currency_code: str):
self.m = decimal.Decimal(money_amount)
self.c = str(currency_code)
self.d = currency_dictionary()
def __repr__(self):
return 'Money({}, {})'.format(self.m, self.c)
def __eq__(self, other):
if type(other) != Money:
return False
elif self.c == other.c:
return self.m == other.m
elif self.c != other.c:
dictionary_key1 = self.d[self.c]
decimal_point1 = dictionary_key1[0]
conversion_factor1 = dictionary_key1[1]
x = self.m / conversion_factor1
dictionary_key2 = self.d[other.c]
decimal_point = dictionary_key2[0]
conversion_factor = dictionary_key2[1]
y = other.m / conversion_factor
return x == y
def __ne__(self, other):
if type(other) != Money:
return True
elif self.c == other.c:
return self.m != other.m
elif self.c != other.c:
dictionary_key1 = self.d[self.c]
decimal_point1 = dictionary_key1[0]
conversion_factor1 = dictionary_key1[1]
x = self.m / conversion_factor1
dictionary_key2 = self.d[other.c]
decimal_point = dictionary_key2[0]
conversion_factor = dictionary_key2[1]
y = other.m / conversion_factor
return x != y
def __add__(self, other):
if self.c == other.c:
return Money((self.m + other.m), self.c)
elif self.c != other.c:
dictionary_key1 = self.d[self.c]
decimal_point1 = dictionary_key1[0]
conversion_factor1 = dictionary_key1[1]
x = self.m / conversion_factor1
dictionary_key2 = self.d[other.c]
decimal_point = dictionary_key2[0]
conversion_factor2 = dictionary_key2[1]
y = other.m / conversion_factor2
total = x + y
return Money((total * conversion_factor1), self.c)
def __sub__(self, other):
if self.c == other.c:
return Money((self.m - other.m), self.c)
elif self.c != other.c:
dictionary_key1 = self.d[self.c]
decimal_point1 = dictionary_key1[0]
conversion_factor1 = dictionary_key1[1]
x = self.m / conversion_factor1
dictionary_key2 = self.d[other.c]
decimal_point = dictionary_key2[0]
conversion_factor2 = dictionary_key2[1]
y = other.m / conversion_factor2
total = x - y
return Money((total * conversion_factor1), self.c)
class Credit_Card():
def __init__(self, card_number, money_amount: Money, card_limit: int):
if type(money_amount) != Money or type(card_limit) != int:
raise TypeError('one of the types of the parameters entered is not valid')
self.number = card_number
self.amount = money_amount
self.limit = card_limit
def __repr__(self):
return 'Card#{}({}, {})'.format(self.number, self.amount, self.limit)
def user_interface():
boolean = True
while boolean:
temp_list = []
command = input()
if command.split()[0] == 'ISSUE':
if len(command.split()) == 3:
x = "%0.5d" % random.randint(0,99999)
currency_code = command.split()[1]
card_limit = int(command.split()[2])
if card_limit < 0:
print("NEGATIVE_LIMIT")
elif not currency_dictionary()[currency_code]:
print("NO_SUCH_CURRENCY")
else:
for card in creditcard_list:
temp_list.append(card.number)
if x not in temp_list and currency_dictionary()[currency_code]:
creditcard_list.append(Credit_Card(x, Money(0, currency_code), card_limit))
print('ISSUED', x)
print(creditcard_list)
else:
print("INVALID_ISSUE_COMMAND")
elif command.split()[0] == 'CANCEL':
templist2 = []
if len(command.split()) == 2:
card_number = command.split()[1]
for card in creditcard_list:
templist2.append(card)
for i, card in enumerate(templist2):
if card_number not in templist2[i].number:
print('NO_SUCH_CARD')
elif templist2[i].amount.m != 0:
print('NONZERO_BALANCE')
elif templist2[i].number == command.split()[1] and card.amount.m == 0:
del creditcard_list[i]
print('CANCELLED', card_number)
print(creditcard_list)
elif command.split()[0] == 'PURCHASE':
if len(command.split()) == 4:
card_number = command.split()[1]
currency_code = command.split()[2]
amount = int(command.split()[3])
if currency_code not in currency_dictionary().keys():
print('NO_SUCH_CURRENCY')
elif amount < 0:
print('NONPOSITIVE_AMOUNT')
else:
for i, card in enumerate(creditcard_list):
if card.number == card_number and 0 <= amount <= card.limit :
x = card.amount + Money(amount, currency_code)
creditcard_list[i] = Credit_Card(card.number, x, card.limit)
elif creditcard_list[i].number != card_number:
print('NO_SUCH_CARD')
elif amount > creditcard_list[i].limit:
print('OVER_LIMIT')
elif command.split(0) == 'PAYMENT':
print(creditcard_list)
if __name__ == '__main__':
user_interface()
My output for the cancel command basically looks like this, and I'm pretty sure once I figure this out I'll be able to deal with the rest. Bold is input, non-bold is output.
**ISSUE USD 5000**
ISSUED 50695
[Card#50695(Money(0, USD), 5000)]
**ISSUE RON 3000**
ISSUED 25282
[Card#50695(Money(0, USD), 5000), Card#25282(Money(0, RON), 3000)]
**CANCEL 25282**
[Card#50695(Money(0, USD), 5000), Card#25282(Money(0, RON), 3000)]
*NO_SUCH_CARD*
CANCELLED 25282
[Card#50695(Money(0, USD), 5000)]
Note that the lists are only printed out for me to keep track of what cards are currently in the main list, and I will eventually remove those print statements. I have italicized the output I'm having a problem with.
The problem appears to be that you're modifying creditcard_list at the same time you are iterating through it. You should first create a temporary copy of the list to iterate through while later removing items from the actual list.
Edit: Ahh, it's printing "NO_SUCH_CARD" on the first card in the list! Not on the second. So in your example, you loop through a list of two; it first visits card #50695, which is not equal to 2582, so it prints "NO_SUCH_CARD". Then it visits 25282, deletes it, and prints "CANCELED". It's doing exactly what you wrote it to do. Instead, just loop through, deleting the card if you find it and silently skipping any card that doesn't match. In the end, if the card is not found print "NO_SUCH_CARD"
Edit2: Here's an example:
found = False
for card in templist2:
if card_number == card.number:
if card.amount.m != 0:
print('NONZERO_BALANCE')
else:
del creditcard_list[i]
print('CANCELLED', card_number)
found = True
break
if not found:
print('NO_SUCH_CARD')

Categories

Resources