positional argument OSX - python

mac terminal says im passing two positional arguments into the take_damage method...
from enemy import Enemy
random_monster = Enemy("Basic enemy", 12, 1)
print(random_monster)
random_monster.take_damage(4)
print(random_monster)
and the other file is here ______________________
class Enemy:
def __init__(self, name="Enemy", hit_points = 0, lives = 1):
self.name = name
self.hit_points = hit_points
self.lives = lives
def take_damage(damage):
remaining_points = self.hit_points - take_damage
if remaining_points >= 0:
self.hit_points = remaining_points
print("i took {} damage and have {} left".format(damage, self.hit_points))
else:
self.lives -= 1
def __str__(self):
return "Name: {0.name}, Lives: {0.lives}, Hitpoints: {0.hit_points}".format(self)

All methods need to take self as well as any other arguments.
def take_damage(self, damage):

Related

AttributeError: 'NoneType' object has no attribute 'hero_first'

I keep getting this, have no idea how to make it work, I'm kinda new at python coding and this is giving me a headacke. Could not find any answer at all so please, just tell me what to do
'''
from tkinter import *
import random
import time
# Variables
# Player
class Player(object):
health = random.randint(70,100)
strength = random.randint(70,80)
defence = random.randint(45,55)
speed = random.randint(40,50)
luck = random.randint(40,50)
def __init__(self, arg):
super(Player, self).__init__()
self.arg = arg
# Beast
class Beast(object):
health = random.randint(60,90)
strength = random.randint(60,90)
defence = random.randint(40,60)
speed = random.randint(40,60)
luck = random.randint(25,40)
def __init__(self, arg):
super(Beast, self).__init__()
self.arg = arg
def begin():
print("\nHero"," Beast"
"\nHealth:", Player.health, " Health:", Beast.health,
"\nStrength:", Player.strength, " Strength:",Beast.strength,
"\nDefence:", Player.defence, " Defence:", Beast.defence,
"\nSpeed:", Player.speed, " Speed:", Beast.speed,
"\nLuck:", Player.luck, " Luck:", Beast.luck)
print("\nBEGIN FIGHT")
def round_stat():
print("Hero"," Beast",
"\nHealth:", Player.health," Health:", Beast.health)
def who_move():
hero_first = 1
if Player.speed > Beast.speed:
hero_first = 1
elif Player.speed < Beast.speed:
hero_first = 0
else:
if Player.luck > Beast.luck:
hero_first = 1
else:
hero_first = 0
begin()
round_stat()
who_move()
if who_move().hero_first == 1:
print("SUPPPPPPP")
'''
who_move() is function, not an object. So you can not access variable inside function.
So the quickest solution is set the hero_first as global:
def who_move():
global hero_first
hero_first = 1
who_move()
if hero_first == 1:
print("SUPPPPPPP")
and then I got:
dubak#dubak-thinkpad:~/projects/$ python3 test.py
SUPPPPPPP
or rewrite the who_move function so it is returning directly value of hero_first. Something like this:
def who_move():
hero_first = None
if 2 > 1:
hero_first = 1
return hero_first
if who_move() == 1:
print("SUPPPPPPP")
You cannot access the internal variables of a function using the . syntax. If you want that data to be accessible outside of the function, return it:
def who_move():
if Player.speed > Beast.speed:
return 1
elif Player.speed < Beast.speed:
return 0
else:
if Player.luck > Beast.luck:
return 1
else:
return 0
Then, use it like:
if who_move() == 1
The other answer mentions global, but I would not use that here. Use of global should be limited, as it has a general tendency of making your code harder to maintain and understand.

Writing a test in python

Im currently taking a python class and im new in programming. I have written the code below and want to write a code that tests if the ResilientPlayer actually does what it is supposed to. The code is from a chutes and ladders board game where the ResilientPlayer is a "special" type of player that gets a "superpower" in its next move afther falling down a chute. The next round afther he has fallen down a chute, he will add a given or a default number to the die_roll, and I want to test if my code actually does this! Hope someone can help me with this problem :)
class Player:
def __init__(self, board):
self.board = board
self.position = 0
self.n_steps = 0
def move(self):
die_roll = random.randint(1, 6)
self.position = self.get_position() + die_roll
self.board.position_adjustment(self.position)
self.n_steps += 1
def get_position(self):
return self.position
def get_steps(self):
return self.n_steps
class ResilientPlayer(Player):
default_extra_steps = 1
def __init__(self, board, extra_steps=None):
super().__init__(board)
self.extra_steps = extra_steps
if self.extra_steps is None:
self.extra_steps = self.default_extra_steps
def move(self):
if self.get_position() in self.board.chutes.values():
die_roll = random.randint(1, 6)
self.position = self.get_position() + die_roll + self.extra_steps
self.board.position_adjustment(self.position)
self.n_steps += 1
else:
super().move()
def get_position(self):
return self.position
def get_steps(self):
return self.n_steps
The best way to do this is using the unittest class, I do this as following:
import unittest
from .... import ResilientPlayer
class TestResilientPlayer(unittest.TestCase):
def setUp(self):
self.resilient_player = ResilientPlayer(....)
def test_move(self):
# Do stuff
self.assertEqual(1, 1)
if __name__ == '__main__':
unittest.main()
Here, unittest.main() will run all the tests in the file. setUp is run before each test (so you can have multiple tests with the same starting conditions).
This is an incredible useful module and I strongly suggest reading more on it, check the documentation

[Closed for the moment]Python class definition is not defined. Error

I am programming on my phone. I've created the class character to hold all the information about the character such as the Hp.
After defining the hp, I make a function called getHp() which returns the hp.
Later when I call "getHp()" in my "stats()" function it says that "getHp()" is not defined. It does the same for all my functions in my class.
Just fyi "stats()" is just a function to gather all my variables (within the class) and print them.
#Adventure game
import random, time
#===========================#
class character():
self.xp = 0
def getLvl(self, xp):
if xp < 5:
level = 1
elif xp < 20:
level = 2
elif xp < 60:
level = 3
elif xp < 120:
level = 4
else:
level = 5
return level
self.level = getLvl(self, xp)
#-----------------------------------------#
self.inventory = {"knife": 1 , "bread": 2 , "gold": 10}
self.armor = 0
#-----------------------------------------#
self.attack = 6
def getAttack(self, attack):
return attack
#-----------------------------------------#
self.dmg = 1
def getDmg(self, dmg):
return dmg
#-----------------------------------------#
self.hp = 10 * level + armor
def getHp(self, hp):
return hp
def updateHp(self, playerHp):
self.hp = playerHp
#-----------------------------------------#
def stats(self):
self.getLvl(xp)
self.getHp(hp)
self.getAttack(attack)
self.getDmg(dmg)
print("Player: \n")
print("Hp: ", hp, "\nLvl: ", level, "\nAttack: ", attack, "\nDmg: ", dmg)
print("Inventory: ", self.inventory)
#===========================#
character.stats()
When you are calling the functions within the class, are you using "self"? In your stats() method it should look like this:
def stats(self):
self.getHp()
This is a way that python knows to refer to the getHp() within the class.
You can find more on Classes and self in the python documentations
https://docs.python.org/3/tutorial/classes.html

How do i create an object with random value of attributes through for loops in python?

Good day, I can't make the value of my attributes random every time I create an object through a for loop. My goal in this code is that when I instantiate an object, self.hunger and self.boredom of each object have different value from 0 - 20 but every time I print the critters dictionary through a for loop their self.hunger and self.boredom is the same. How can I make it random? And can you explain it to me why my code didn't work? Here is my some pieces of my code. Any answer is greatly appreciated.
class Critter(object):
"""A virtual pet"""
import random
def __init__(self, name, hunger = random.randrange(0, 21), boredom = random.randrange(0, 21)):
self.name = name
self.hunger = hunger
self.boredom = boredom
def __str__(self):
rep = "\nCritter object\n"
rep += "Name: " + str(self.name) + ", Hunger: " + str(self.hunger) + ", Boredom: " + str(self.boredom)
return rep
def main():
critters = {}
crit_name = input("What do you want to name to your critter?: ")
critters[1] = Critter(crit_name)
choice = None
while choice != "0":
print \
("""
Critter Caretaker
0 - Quit
1 - Listen to your critters
2 - Feed your critters
3 - Play with your critters
4 - Create another critter
""")
elif choice == "4":
crit_name = input("What do you want to name your critter?: ")
for i in range(len(critters) + 1, 11):
critters[i] = Critter(crit_name)
break
if i == 10:
print("\nMaximum critters reached. Cannot create another critter.")
If you want the whole program to understand my question, I will edit my question. Please help me.
This is happening because you are passing the random values as default arguments and they are evaluated only once. Try in this way:
import random
class Critter(object):
"""A virtual pet"""
def __init__(self, name, hunger=None, boredom=None):
self.name = name
self.hunger = hunger if hunger is not None else random.randrange(0, 21)
self.boredom = boredom if boredom is not None else random.randrange(0, 21)
def __str__(self):
rep = "\nCritter object\n"
rep += "Name: " + str(self.name) + ", Hunger: " + str(self.hunger) + ", Boredom: " + str(self.boredom)
return rep
Default parameter values are always evaluated when, and only when, the “def” statement they belong to is executed.
Thus, it is happening before default arguments to functions(or methods) are evaluated only once. So, assign the default values in initializer instead if you want different random values.
class Critter(object):
"""A virtual pet"""
import random
def __init__(self, name, hunger = None, boredom = None):
self.name = name
self.hunger = random.randrange(0, 21) if hunger is None else hunger
self.boredom = random.randrange(0, 21) if boredom is None else boredom
is evaluated only once. Although if None is a valid value passed in arguments as pointed out by #jonrsharpe, then you need a different solution
class Nil(object):
pass
nil = Nil()
class Critter(object):
"""A virtual pet"""
import random
def __init__(self, name, hunger = nil, boredom = nil):
self.name = name
self.hunger = random.randrange(0, 21) if hunger is nil else hunger
self.boredom = random.randrange(0, 21) if boredom is nil else boredom
If you want to be able to set hunger or boredom, but also allow it to default to something random:
def __init__(self, name, hunger = None, boredom = None):
self.name = name
self.hunger = hunger if hunger is not None else random.randrange(0, 21)
self.boredom = boredom if boredom is not None else random.randrange(0, 21)
What you had was, as in xkcd, effectively:
def get_random_number():
return 4 # chosen by a fair dice roll.
# guaranteed to be random.

Basic Python Inheritance Issue

I have the following two classes set up:
class Player:
POINTS_PER_PASSING_YARD = 0.04
POINTS_PER_PASSING_TOUCHDOWN = 4
POINTS_PER_INTERCEPTION = -1
POINTS_PER_RUSHING_YARD = 0.1
POINTS_PER_RUSHING_TOUCHDOWN = 6
POINTS_PER_RUSHING_FUMBLE = -2
POINTS_PER_RECEPTION_YARD = 0.1
POINTS_PER_RECEPTION_TOUCHDOWN = 6
def __init__(self, name, team, rushingYards, rushingTouchdowns, rushingFumbles):
self.name = name
self.team = team
self.rushingYards = rushingYards
self.rushingTouchdowns = rushingTouchdowns
self.rushingFumbles= rushingFumbles
def calculatePoints(self):
return self.rushingYards * POINTS_PER_RUSHING_YARD + self.rushingTouchdowns * POINTS_PER_RUSHING_TOUCHDOWN + self.rushingFumbles * POINTS_PER_RUSHING_FUMBLE
def toString(self):
return "name: " + self.name + " team: " + self.team + " passing yards: " + self.passingYards + " rushing yards: " + self.rushingYards + " touchdowns: " + self.touchdowns + " interceptions: " + self.interceptions
Then I have a QB class that inherits from Player:
from Player import *
class QB(Player):
def __init__(self, name, team, rushingYards, rushingTouchdowns, rushingFumbles, passingYards, passingTouchdowns, interceptions, position="QB"):
super().__init__(self, name, team, rushingYards, rushingTouchdowns, rushingFumbles)
self.passingYards = passingYards
self.passingTouchdowns = passingTouchdowns
self.interceptions = interceptions
def toString(self):
return "position: " + self.position + super().toString()
Then in my main class, I simply do:
myQB = QB("Brees", "Saints", 0, 0, 0, 4952, 33, 17)
print(myQB)
I'm getting the following error:
Traceback (most recent call last):
File "main.py", line 35, in <module>
main()
File "main.py", line 32, in main
myQB = QB("Brees", "Saints", 0, 0, 0, 4952, 33, 17)
File "/Users/benjaminclayman/Desktop/Aurora_Fantasy_Football/QB.py", line 5, in __init__
Player.__init__(self, name, team, rushingYards, rushingTouchdowns, rushingFumbles)
TypeError: object.__init__() takes no parameters
But I'm not sure why, since all of the init methods I've written do take parameters...
Any idea what's going wrong?
Thanks,
bclayman
If your indentation in the first script (with the Player class) is correct, then that is the issue.
According to your indentation , the __init__() method and other methods are outside the class Player , so Player uses object class' __init__() , which does not take any parameters (other than self , though we do not need to pass it explicitly ).
You may want to fix the indentation so that all the instance methods (that you intended to be inside Player class) come inside the Player class.
Example -
class Player:
POINTS_PER_PASSING_YARD = 0.04
POINTS_PER_PASSING_TOUCHDOWN = 4
POINTS_PER_INTERCEPTION = -1
POINTS_PER_RUSHING_YARD = 0.1
POINTS_PER_RUSHING_TOUCHDOWN = 6
POINTS_PER_RUSHING_FUMBLE = -2
POINTS_PER_RECEPTION_YARD = 0.1
POINTS_PER_RECEPTION_TOUCHDOWN = 6
def __init__(self, name, team, rushingYards, rushingTouchdowns, rushingFumbles):
self.name = name
self.team = team
self.rushingYards = rushingYards
self.rushingTouchdowns = rushingTouchdowns
self.rushingFumbles= rushingFumbles
You will need to do this for all methods you intended to be inside Player class.
One more issue, you should not pass self in to te __init__() method called using super() .
Example -
class QB(Player):
def __init__(self, name, team, rushingYards, rushingTouchdowns, rushingFumbles, passingYards, passingTouchdowns, interceptions, position="QB"):
super().__init__(name, team, rushingYards, rushingTouchdowns, rushingFumbles)
Few issues, first you need to fix your indentation.
second, you should change
this class Player:
TO
class Player(object):
another issue is when you call a static member this is the way to handle them:
Player.POINTS_PER_RUSHING_YARD # name of the class and then the static member.
This is how your super should look like:
super(QB, self).__init__(name, team, rushingYards, rushingTouchdowns, rushingFumbles)
This is the code:
class Player(object):
POINTS_PER_PASSING_YARD = 0.04
POINTS_PER_PASSING_TOUCHDOWN = 4
POINTS_PER_INTERCEPTION = -1
POINTS_PER_RUSHING_YARD = 0.1
POINTS_PER_RUSHING_TOUCHDOWN = 6
POINTS_PER_RUSHING_FUMBLE = -2
POINTS_PER_RECEPTION_YARD = 0.1
POINTS_PER_RECEPTION_TOUCHDOWN = 6
def __init__(self, name, team, rushingYards, rushingTouchdowns, rushingFumbles):
self.name = name
self.team = team
self.rushingYards = rushingYards
self.rushingTouchdowns = rushingTouchdowns
self.rushingFumbles= rushingFumbles
def calculatePoints(self):
return self.rushingYards * Player.POINTS_PER_RUSHING_YARD + self.rushingTouchdowns * Player.POINTS_PER_RUSHING_TOUCHDOWN + self.rushingFumbles * Player.POINTS_PER_RUSHING_FUMBLE
def toString(self):
return "name: " + self.name + " team: " + self.team + " passing yards: " + self.passingYards + " rushing yards: " + self.rushingYards + " touchdowns: " + self.touchdowns + " interceptions: " + self.interceptions
class QB(Player):
def __init__(self, name, team, rushingYards, rushingTouchdowns, rushingFumbles, passingYards, passingTouchdowns, interceptions, position="QB"):
super(QB, self).__init__(name, team, rushingYards, rushingTouchdowns, rushingFumbles)
self.passingYards = passingYards
self.passingTouchdowns = passingTouchdowns
self.interceptions = interceptions
def toString(self):
return "position: " + self.position + super(Player).toString()
myQB = QB("Brees", "Saints", 0, 0, 0, 4952, 33, 17)
print(myQB)
In Python the indentation plays the major role.
List of Issues:
1) The __init__() should be within the class Player. Otherwise your initialization will not work.
2) The Other functions def calculatePoints(self), should also be within the class Player. Currently in your code it is defined outside the class.
3) The def toString(self) should also be within the class Player.
3.1) Also the concatenation of string and int is not permitted.
3.2) The variable `self.touchdowns` is not initialized in the def toString of class Player.
3.3) The alternate way to print the class with significant information
about class can be written in this manner.
class Player:
POINTS_PER_PASSING_YARD = 0.04
POINTS_PER_PASSING_TOUCHDOWN = 4
POINTS_PER_INTERCEPTION = -1
POINTS_PER_RUSHING_YARD = 0.1
POINTS_PER_RUSHING_TOUCHDOWN = 6
POINTS_PER_RUSHING_FUMBLE = -2
POINTS_PER_RECEPTION_YARD = 0.1
POINTS_PER_RECEPTION_TOUCHDOWN = 6
def __init__(self, name, team, rushingYards, rushingTouchdowns, rushingFumbles):
self.name = name
self.team = team
self.rushingYards = rushingYards
self.rushingTouchdowns = rushingTouchdowns
self.rushingFumbles= rushingFumbles
def calculatePoints(self):
return self.rushingYards * POINTS_PER_RUSHING_YARD + self.rushingTouchdowns * POINTS_PER_RUSHING_TOUCHDOWN + self.rushingFumbles * POINTS_PER_RUSHING_FUMBLE
def __str__(self):
return "name: %s team: %s passing yards: %r rushing yards: %r rushingTouchdowns: %r interceptions: %r" % (self.name, self.team, self.passingYards, self.rushingYards, self.rushingTouchdowns ,self.interceptions)
4) self.position = position need to be initialized in the class QB, like this:
class QB(Player):
def __init__(self, name, team, rushingYards, rushingTouchdowns, rushingFumbles, passingYards, passingTouchdowns, interceptions, position="QB"):
super().__init__(name, team, rushingYards, rushingTouchdowns, rushingFumbles)
self.passingYards = passingYards
self.passingTouchdowns = passingTouchdowns
self.interceptions = interceptions
self.position = position
def __str__(self):
return "position: " + self.position + super().__str__()

Categories