I don't understand what is wrong. I keep getting that I'm missing a required positional argument.
class CoinToss(object):
def __init__(self, flip, ID_Num, Value):
self.flip = flip
self.ID_Num = ID_Num
self.Value = Value
def Flip(self):
"""
Method is important in determining the number of flips and simulating the coin
"""
data = []
Num_flip = int(input("how many times do you want to flip the coin? :"))
print("the ball at the start: ball: d%, state: d% value: d% " %(self.ID_Num))
for i in range(Num_flip):
self.flip = self.flip = 1
if randint(0,1) == 0:
self.Value = self.Value + 1
data.append(self.value)
else:
self.Value = self.Value - 1
data.append(self.Value)
Apparently, when you use CoinToss, you call it with only 2 arguments, flip and ID_NUM. This would cause an error, because you did not provide CoinToss.__init__() with the required Value argument.
Related
A very simple problem, yet I need some assistance. I have created a class that has some default values. After that an instance takes the values based on an input. If one of the properties is "null" how can I assign the default value to it?
class Dragon:
dragons=[]
def __init__(self,dragon_type,name,health=2000,attack=450,fly_speed=120):
self.dragon_type=dragon_type
self.name=name
self.health=health
self.attack=attack
self.fly_speed=fly_speed
Dragon.dragons.append(self)
num=int(input())
for n in range(num):
entry=input().split() #fire Azzaaxx null 480 null
dragon_type,name,health,attack,fly_speed=entry[0],entry[1],entry[2],entry[3],entry[4]
if health=="null":
health=... #2000
else:
health=int(health)
if attack=="null":
attack=... #450
else:
attack=int(attack)
if fly_speed=="null":
fly_speed=... #120
else:
fly_speed=int(fly_speed)
obj=Dragon(dragon_type,name,health,attack,fly_speed)
Is this approach acceptable or this should be defined differently?
Thank you in advance!
Change the class definition so that None values are converted to the default.
class Dragon:
dragons=[]
def __init__(self,dragon_type,name,health=None,attack=None,fly_speed=None):
self.dragon_type=dragon_type
self.name=name
self.health=health if health is not None else 2000
self.attack=attack if attack is not None else 450
self.fly_speed=fly_speed if fly_speed is not None else 120
Dragon.dragons.append(self)
Then you can set the variables in the caller to None if the user enters null, and the __init__() method will do the right thing, so you don't have to repeat the default values.
Build up a dictionary of non-null values to use as keyword arguments.
args = {}
if health != "null":
args['health'] = int(health)
if attack != "null":
args['attack'] = int(attack)
if fly_speed != "null":
args['fly_speed'] = int(fly_speed)
obj = Dragon(dragon_type, name, **args)
However, this is a good opportunity to move the handling of "missing" values to a class method. __init__ should require values; the class method will provide defaults when its own input is lacking.
class Dragon:
dragons = []
def __init__(self, dragon_type, name, health: int, attack: int, fly_speed: int):
self.dragon_type = dragon_type
self.name = name
self.health = health
self.attack = attack
self.fly_speed = fly_speed
Dragon.dragons.append(self)
#classmethod
def from_input(cls):
entry = input().split()
health = int(entry[2]) if entry[2] != "null" else 2000
attack = int(entry[3]) if entry[3] != "null" else 450
speed = int(entry[4]) if entry[4] != "null" else 120
return cls(entry[0], entry[1], health, attack, speed)
num = int(input())
for n in range(num):
obj = Dragon.from_input()
I am building a battle simulation program. Running into TypeError. Unable to resolve. Any help would be appreciated. I can't seem to get the iadd function working. I'm trying to add new Pokemon objects to the existing PokemonTrainer object by using the iadd function in python. Anyone has any ideas on how to execute this?
main.py
name = input("State your name: ")
player = PokemonTrainer(name)
player += Pokemon("Staryu", ElementType.WATER, [
Move("water blast", ElementType.WATER, 5),
Move("water cyclone", ElementType.WATER, 6)
])
pokemon_trainer.py
For the iadd, I'm using type-based dispatch to deal with the parameter. If it is of type Pokemon, call the add_pokemon method on self and then return the self object. If it is of type Item, call the add_item method on self and then return the self object. Otherwise, raise a TypeError.
from pokemon import Pokemon
class PokemonTrainer:
def __init__(self, name, pokemon = [], items = [], current_active_pokemon = None):
self.name = name
self.pokemon = pokemon
self.items = items
self.current_active_pokemon = current_active_pokemon
def __iadd__(self, other):
self.pokemon.append(other)
if (type(other) == type(Pokemon)):
self.add_pokemon(other)
elif (type(other) == type(Item)):
self.add_item(other)
else:
raise TypeError("Only Pokemon or Item type are allowed")
return self
def add_pokemon(self, pkmn):
self.pokemon.append(pkmn)
if (self.current_active_pokemon == None):
self.current_active_pokemon = pkmn
def add_item(self, item):
self.items.append(item)
pokemon.py
class Pokemon:
def __init__(self, name, pokemon_type, moves):
self.name = name
self.pokemon_type = pokemon_type
self.moves = moves
self.level = 1
self.exp = 0
self.max_hp = 100
self.current_hp = self.max_hp
self.attack_power = 1
self.defense_power = 1
self.fainted = False
I guess you want isinstance(other, Pokemon) instead of type(other) == type(Pokemon).
https://docs.python.org/3/library/functions.html#isinstance
Also relevant here: What are the differences between type() and isinstance()?
Im trying to write a python method that looks at Rarity and counts the different types and then returns what the smallest count is but i keep getting: 'MagicCard' object is not subscriptable. Im also wanting to check which colors are associated with the least rare cards. Any help would be appreciated:
Here is where the Json can be obtained from for testing: http://mtgjson.com/json/DTK.json
Card Object:
class MagicCard(object):
def __init__ (self, jsonCard):
self.name=jsonCard["name"]
if jsonCard.get("colors",""):
self.colors=jsonCard["colors"]
else:
self.colors=None
if jsonCard["rarity"]:
self.rarity=jsonCard["rarity"]
else:
self.rarity=None
def get_name(self):
"""Return the name of the card"""
return self.name
def get_colors(self):
"""Return the colors of the card"""
return self.colors
def get_rarity(self):
"""Return the rarity of the card"""
return self.rarity
Card Deck Object:
class MagicCardSet(object):
def __init__(self, DeckDict):
self.cardlist = [MagicCard(eachCard) for eachCard in DeckDict["cards"]]
def get_card_list(self):
Card_name_list=[]
for newCard in self.cardlist:
Card_name_list.append(newCard.get_name())
return(Card_name_list)
def get_card_color(self):
color_list=[]
for newCard in self.cardlist:
color_list.append(newCard.get_color())
return(color_list)
def get_card_rarity(self):
rarity_list=[]
for newCard in self.cardlist:
rarity_list.append(newCard.get_rarity())
return(rarity_list)
def get_rarest_card(self):
for eachCard in self.cardlist:
if eachCard["rarity"]=="Uncommon":
uncommon_counter = uncommon_counter + 1
elif eachCard["rarity"]=="Common":
common_counter=common_counter + 1
elif eachCard["rarity"]=="Rare":
rare_counter = rare_counter + 1
elif eachCard["rarity"]=="Mythic Rare":
mythic_rare_counter = mythic_rare_counter + 1
return(mythic_rare_counter)
error:
The
for eachCard in self.cardlist
returns a MagicCard instance. Call get_rarity() and get_name() and get_colors() on eachCard.
Also, to get the colors of the least rare (most common) cards:
unrare_colors = {}
for eachCard in self.cardlist:
if eachCard.get_rarity() == "Common":
for eachColor in eachCard.get_colors():
unrare_colors[eachColor] = 1
for color in unrare_colors.keys():
print(color)
Running the program will cause an error message:
TypeError: unsupported operand type(s) for +=: 'int' and 'NoneType'
The problem is with the line value += values.get(card.get_rank)
I think there may be a problem with the get_rank method? Does it not return an integer?
ranks = ('A','2','3','4','5','6','7','8','9','10','J','Q','K')
values = {'A':1,'2':2,'3':3,'4':4,'5':5,'6':6,'7':7,'8':8,'9':9,'10':10,'J':10,'Q':10,'K':10}
suits = ('Diamonds','Hearts','Clubs','Diamonds')
class Card:
def __init__(self, suit, rank):
self.suit = suit
self.rank = rank
def __str__(self, suit, rank):
print (self.rank + 'of' + self.rank)
def get_rank(self):
return self.rank
class Hand:
def __init__(self):
self.hand = []
def __str__(self):
hand = ''
for card in self.hand:
hand = hand + str(card)
return hand
def get_value(self):
value = 0
aces = 0
for card in self.hand:
if card.get_rank == 'A':
aces += 1
value += values.get(card.get_rank)
if (aces>0) and (value + 10 <= 21):
value += 10
return value
values.get(card.get_rank) tries to use the instance method as the key for the dictionary. This is not a valid key in the dictionary, so dict.get() returns the default None.
Instead you want to call the method, and use the return value as the key:
value += values.get(card.get_rank())
or, as trivial getters and setters are unpythonic, just access the attribute directly:
value += values.get(card.rank)
Note that you can also pass a default to dict.get() to ensure you always get a sensible return value:
value += values.get(card.rank, 0)
Now if there is no value for that card rank in values, its value is assumed to be zero.
Also, it's not clear where values is coming from. I would suggest you make it a class attribute:
class Hand:
VALUES = {...}
...
def get_value(self):
...
value += self.VALUES.get(card.rank, 0)
...
Or an explicit argument to get_value:
class Hand:
...
def get_value(self, values):
...
value += self.values.get(card.rank, 0)
...
I have a class with many attributes, and when I give a number, I would like it to subtract that from one attribute, but if the amount is greater than the attribute subtracted from, move to the next attribute with what is left over. Example:
def subt(self, amount):
self.attr1 += amount
if self.attr1 < 0:
self.attr2 += self.attr1
self.attr1 = 0
if self.attr2 < 0:
# etc...
It feel like there should be a concise recursive way to accomplish the same thing, but I don't know how with the all the different attributes.
You can access the attributes using .__dict__ You need a list for the order you want to subtract. Something like this works.
class A():
def __init__(self):
self.foo = 100
self.bar = 200
self.baz = 300
self.sub_stack = ['foo', 'baz', 'bar']
def subt(self, amount):
tmp_stack = self.sub_stack[:]
while tmp_stack and amount:
key = tmp_stack.pop(0)
val = self.__dict__[key]
if val > amount:
self.__dict__[key] -= amount
amount = 0
else:
amount -= self.__dict__[key]
self.__dict__[key]=0
return amount
return value is the remainder on amount after iterating through your attributes
Does making a list out of all the attributes work?
def subt(self, amount):
i = 0
while i<self.attrlist.len:
if attrlist[i] < amount:
attrlist[i] -= amount
break
Yes, the best way is to create a list of all your attributes - do it either manually,
or, if your attribute names follow a pattern (like the attrN series on the example),
you can automate the creation of such a list.
def subt(self, amount):
#all_attrs = ["attr1", "attr2", "attr3"]
# or this step can be automated by something like:
all_attrs = sorted(attr_name for attr_name in self.__class__.__dict__.keys() if attr_name.startswith("attr"))
for i, attr_name in all_attrs:
self.__setattr__(getattr(self, attr_name) + amount)
if gettattr(self, attr_name) < 0:
amount = gettattr(self, attr_name)
self.__setattr__(self, attr_name, 0)
else:
break