I'm quite confused as to how I can pass variables which are set within a function to a method, which is within a class.
Here is the code in question:
class monster():
def __init__(self, health, name):
print(name + " has been born!")
self.name = name
self.health = health
self.stats(name, health)
def stats(self, name, health):
self.name = name
self.health = health
print(self.name + " - " + str(self.health) + " HP")
I create an instance of monster() with this line at the start of the program:
gameMonster = monster(20, name)
However, you can see that the function stats() is supposed to display the name and health of the monster, which is set earlier. The game is in a loop, so the stats() function would be called after each "turn". However, I need to pass the variables name and health to stats() to be able to display them, but can't seem to figure out how.
My question is:
How do I pass the variables, which are declared on initialisation of the method, to another method within the same class?
Any help appreciated.
You don't need to set them again, they already live on the instance:
class Monster(object):
def __init__(self, health, name):
print(name + " has been born!")
self.name = name
self.health = health
self.stats()
def stats(self):
print(self.name + " - " + str(self.health) + " HP")
And usage:
>>> monster = Monster(20, 'Boris')
Boris has been born!
Boris - 20 HP
>>> monster.stats()
Boris - 20 HP
>>> monster.health -= 5
>>> monster.stats()
Boris - 15 HP
Related
I am trying to learn Python OOP and have been struggling to understand scope, passing values and how to encapsulate. My earlier attempts have rapidly become spaghetti code (likely because my only programming experience was on 8 bit BASIC 40 years ago), and thus, I am trying classes and objects.
Here it is:
import random
class Player:
def __init__(self, weapon, health):
self.weapon = weapon
self.health = health
def reduce_health(self, amount):
self.health -= amount
def check_dead(self):
if self.health > 0:
return "Player not dead"
else:
return "Player dead"
def calculate_damage(self, weapon):
damage_inflicted = random.randint(3, 15) + weapon
return damage_inflicted
def fight(self):
player.reduce_health(self.calculate_damage(self.weapon))
print(player.health)
player.check_dead()
player = Player(1, 15)
player.fight()
The calculate_damage function is flagged as being 'static' and the check_dead function seemingly has no effect at all.
I need some hints to get my footing. Thanks.
There are a few errors in your code.
First, you are using the player variable in the fight function. This works, because you've called the instance of the Player class player, but it wouldn't if you would give it any other name. To fix your issue, use self instead ofplayer in all class functions. The self argument is automatically passed in by python and does always refer to the object on which the the function is called.
Second, the check_deadfunction does nothing because it only returns a value. There is no attribute set or value printed out in this function. In order to make it work, you need to print the value, either inside the function or outside, with the return value of the function.
This code should work:
import random
class Player:
def __init__(self, weapon, health):
self.weapon = weapon
self.health = health
def reduce_health(self, amount):
self.health -= amount
def check_dead(self):
if self.health > 0:
return "Player not dead"
else:
return "Player dead"
def calculate_damage(self, weapon):
damage_inflicted = random.randint(3, 15) + weapon
return damage_inflicted
def fight(self):
self.reduce_health(self.calculate_damage(self.weapon))
print(player.health)
print(self.check_dead())
player = Player(1, 15)
player.fight()
In this code, we print the aliveness of the player directly instead of returning it:
import random
class Player:
def __init__(self, weapon, health):
self.weapon = weapon
self.health = health
def reduce_health(self, amount):
self.health -= amount
def check_dead(self):
if self.health > 0:
print("Player not dead")
else:
print("Player dead")
def calculate_damage(self, weapon):
damage_inflicted = random.randint(3, 15) + weapon
return damage_inflicted
def fight(self):
self.reduce_health(self.calculate_damage(self.weapon))
print(player.health)
self.check_dead()
player = Player(1, 15)
player.fight()
The problem that you are having is probably due to the way you refer to the functions of check_dead(), reduce_health() and the variable health in fight(). You are calling out the player class instance, instead of the instance the function is running in, that meant that, if you were to change the name of the player class instance to something different, it would spill out an error that "player is not defined".
Why the check_dead() is not working could also be because it doesn't print out the values, it just returns them, and it you don't do anything with them when it returns them to the calling function it just scraps them.
I recommend checking the code if it is spelled right and also replace every reference in the class to self. And also make the check_dead() function wrapped in print in the fight() function. That would end up looking something like this:
import random
class Player:
def __init__(self, weapon, health):
self.weapon = weapon
self.health = health
def reduce_health(self, amount):
self.health -= amount
def check_dead(self):
if self.health > 0:
return "Player not dead"
else:
return "Player dead"
def calculate_damage(self, weapon):
damage_inflicted = random.randint(3, 15) + weapon
return damage_inflicted
def fight(self):
self.reduce_health(self.calculate_damage(self.weapon))
print(self.health)
print(self.check_dead())
player = Player(1, 15)
player.fight()
If this still doesn't work it's propablly of your running environment or your ide/editor.
Also:
Static means, that the function standalone
If a function is static it doesn't use any of the functions/variables the class gives it (which are commonly gotten by using self.[function/variable name]). By that it is independent and it could be written outside of the class and it would still work as intended.
when a method call by use of an instance, the IDE displays an error that the constructor takes no argument on running the code
I have tried using double underscores in the init method
class Hotel():
"""displays a hotel's information"""
def __init__(name, cuisine):
"""shows details."""
#self.name = name
#self.cuisine = cuisine
def describe_restaurant(self):
"""prints two pieces information."""
print("Welcome to" + name + ".")
print("Where " + cuisine + "." "is offered")
#+ "la" + cuisine_type + ".")
def open_restaurant(self):
"""Indicates when restaurant is open."""
print("It is open at 09:00am everyday")
my_hotel = Hotel('De La Rue', 'haute')
print("My hotel's name is " + my_hotel.hotel_name.title() + "." )
my_hotel.describe_restaurant()
my_hotel.open_restaurant()
I expected the output my hotel's name is De La Rue
You're missing the self argument in your constructor
def __init__(self, name, cuisine):
(and you also need to uncomment out its contents)
I am currently developing a short text-based adventure so I can learn how to use Classes within Python. As part of this, I am trying to create a combat system where the player could choose an NPC to attack.
The aim is that the player can enter the name of the NPC and the weapon they want to use. A method in the target's class will then be called, to lose health based on the damage of the weapon.
My current code is below:
class npc:
def __init__(self, name, alliance):
self.name = name
self.alliance = alliance
def loseHealth(self, health, dmg):
self.dmg = dmg
self.health = self.health - dmg
def usePotion(self, health, pType):
if pType == "great":
self.health = min(self.health + 50,self.maxHealth)
elif pType == "normal":
self.health = min(self.health + 25,self.maxHealth)
else:
pass
def attack(self, target, weaponDmg):
if target in npcList:
target.loseHealth(self.health, weaponDmg)
class human(npc):
maxHealth = 100
health = 100
def __init__(self, name, alliance):
super().__init__(name, alliance)
class orc(npc):
maxHealth = 200
health = 200
def __init(self, name, alliance):
super().__init__(name, alliance)
weaponDmg = {'sword':10,'axe':20}
alice = human("alice","good")
bob = orc("bob","evil")
npcList = [alice, bob]
target = input("Enter Target:")
weapon = input("Enter weapon:")
for x in range(3):
alice.attack(target,weaponDmg[weapon]) #using alice temporarily until I have a person class sorted
print(target.health)
The simple and pythonic answer is to use a dict of NPCs keyed by name, the same way you’re already doing it with weapons:
npcs = {‘alice’: alice, ‘bob’: bob}
target = input("Enter Target:")
weapon = input("Enter weapon:")
for x in range(3):
alice.attack(npcs[target], weaponDmg[weapon])
print(target.health)
And if you want to look up the attacking NPC by user-supplied name as well as the attackee, you can do the same thing there:
npcs[attacker].attack(npcs[target], weaponDmg[weapon])
If you really want to do this inside the attack method you can keep passing in target as a name (string) and do this:
if target in npcs:
npcs[target].loseHealth(self.health, weaponDmg)
... but that probably isn’t a very good design. It means you’re sharing a global variable, and your NPC objects all “know” about that global dict and all the NPCs in it, which doesn’t seem like part of their responsibility.
You can make this a little less repetitive by creating the dict with a comprehension:
npcs = {npc.name: npc for npc in (alice, bob)}
... or by just creating them directly in the dict instead of in variables that you’re probably never going to otherwise use:
npcs = {}
npcs[‘alice’] = human("alice","good")
npcs[‘bob’] = orc("bob","evil")
You can call a method on an instance by using getattr, here is an example:
>>> class Test:
... def my_method(self, arg1, arg2):
... print(arg1, arg2)
...
>>> t = Test()
>>> getattr(t, 'my_method')('foo', 'bar')
foo bar
I'm having some trouble with classes at the minute, and I not sure of how to solve my problem. I've read the docs and I can't connect anything said there with the problem I'm having.
I'm trying to make some simple classes for a game. I have a Weapon class and a Person class. I'm trying to pass a Weapon to the Person class (I hope this makes sense), so that the Person (Bob) can use the weapon. I'm having trouble accessing the methods and attributes in the Weapon class. I've considered making Person a child class of Weapon so that it can call the method easily, but that doesn't seem intuitive to me . . .
class Weapon:
def __init__(self, weapon_name, weapon_damage):
self.weapon_name = weapon_name
self.weapon_damage = weapon_damage
def display_weapon_name(self):
print('Weapon Name: %s' %self.weapon_name)
class Person:
def __init__(self, person_name, health, ranged_weapon):
self.person_name = person_name
self.health = health
Weapon.ranged_weapon = ranged_weapon
def display_person_info(self):
print('Name: %s' %self.person_name)
print('Ranged Weapon :%s' %Weapon.display_weapon_name)
def ranged_attack(self, ranged_weapon, target):
target.health -=ranged_weapon.weapon_damage
print("Weapon: %s" %ranged_weapon.weapon_name)
print(target.person_name + "'s Health: "+str(target.health))
pistol = Weapon("Pistol", 40)
bob = Person("Bob", 100, pistol)
bob.display_person_info()
Running this gives me:
Name: Bob
Ranged Weapon :<function Weapon.display_weapon_name at 0x02E23030>
Running:
bob.ranged_attack(pistol, bob)
Gives:
Weapon: Pistol
Bob's Health: 60
My questions are, am I passing the Weapon object correctly to the Person class? It seems weird writing Weapon.ranged_weapon in _init__ rather than self.ranged_weapon.
How can I get the display_weapon_info to show the string 'Weapon Name: Pistol', rather than the reference? It seems to work when I call it in ranged_attack, but not in the display info.
Really appreciate any help I can get with this. Apologies if a similar question has been asked before, but I couldn't find anything I could relate to my issue.
Rich
Person doesn't actually need to reference the Weapon class directly; it just needs to save a reference to whatever is passed as the ranged_weapon argument and know what it can do with that object. The code implicitly assumes that ranged_weapon is an instance of Weapon, but will work with any object that is suitably similar to an instant of Weapon.
class Person:
def __init__(self, person_name, health, ranged_weapon):
self.person_name = person_name
self.health = health
self.weapon = ranged_weapon
def display_person_info(self):
print('Name: %s' %self.person_name)
# display_weapon_name already calls print; but
# you probably don't need this method at all.
self.weapon.display_weapon_name()
# Instead, do this (actually, you already do this
# in ranged_attack())
# print('Weapon: %s' % self.weapon.weapon_name)
def ranged_attack(self, ranged_weapon, target):
target.health -= self.weapon.weapon_damage
print("Weapon: %s" % self.weapon.weapon_name)
print(target.person_name + "'s Health: "+str(target.health))
def display_person_info(self):
print('Name: %s' %self.person_name)
print('Ranged Weapon :%s' %Weapon.display_weapon_name)
Looking at this function, the compiler sees the following:
Line 1: A function named display_person_info with the parameter self.
Line 2: Print "Name: " and then print the name of self
Line 3: Print "Ranged Weapon: " and then Weapon.display_weapon_name.
In line 3, the compiler, rather than printing the weapon name, it is printing the function display_weapon_name itself! What you need to do instead is replace Line 3 with this:
print('Ranged Weapon :%s' %self.weapon.display_weapon_name())
That way, the value returned by the function is printed, rather than the function's pointer.
this is my first attempt at coding a game with python. I am at trying to run it through codeacademy labs but it says this:
File "<stdin>", line 7
__init__(self, name, size_v, size_h):
^ SyntaxError: invalid syntax Unknown error.
don't be afraid of hurting my feelings I am a very novice coder and I know I'm probably making quite a few mistakes.
I supposed I'm also looking for an explanation or alternative on how to code and experiment in a different setting (i think it's called an IDE)
from datetime import datetime
log = open("log.txt", "a")
class Ocean(object):
__init__(self, name, size_v, size_h):
self.name = name
self.size_v = size_v
self.size_h = size_h
class Ship(object):
__init__(self, size):
self.health = size
self.size = size
class BattleShip(Ship)
__init__(self):
self.health = 4
self.size = 4
class AirCarrier(Ship)
__init__(self):
self.health = 6
self.size = 6
class MedicShip(Ship)
__init__(self, size):
self.health = 2
self.size = 2
class ArmouredShip(Ship)
__init__(self, size):
self.health = 3
self.size = 2
def create_user_profile(username):
user_profile = open(username + "prof", "r+")
def create_default_ocean(name):
ocean = Ocean(name, 20, 20)
return ocean.populate(2,1,1,1)
def mainload():
gametime = datetime.now()
gamestate = "mainmenu"
username = str(raw_input("What is your name? "))
create_user_profile(username)
gametype = str(raw_input("What do you want to play? (QUICKPLAY) (CUSTOM)"))
log.write("[] " + gametime + " [] " + gamestate + " [] " + username + " [] " +gametype")
quick = "quick quickplay qp q"
custom = "custom cust c"
mainload()
if gametype.lower() in quick:
ocean = create_default_ocean(newocean)
elif gametype.lower() in custom:
#get height/width of ocean
#get amount of ships/size
There's 4 kind of errors in your script:
You forget the def identifier before each function:
class Ocean(object):
def __init__(self, name, size_v, size_h):
# ^^^
self.name = name
self.size_v = size_v
self.size_h = size_h
See documentation examples to get the syntax of classes :)
You forget some semicolons after class definition
class MedicShip(Ship):
# ^ this one
You also have a syntax error in the last function (mainload), there's a quote at the end. The correct line is:
log.write("[] " + gametime + " [] " + gamestate + " [] " + username + " [] " +gametype)
Finally, if you want to execute your code, you'll need to put something (other than comments) in the elif block at the end of your file. Otherwise, the interpreter will raise a syntax error (EOF error). Put a pass statement if you don't want to put any code for the moment:
elif gametype.lower() in custom:
pass # <- do nothing but create a correct block for the elif
#get height/width of ocean
#get amount of ships/size
I recommend you to read some beginner Python tutorial to learn the syntax ;)
You should define your function __init__() by writing def __init__(self, size)
also in some places you have forgotten to put ':' after defining class.
If you are a beginner in python u can get tutorial here(official python documentation)
To practice some basic programming stuff go to www.codingbat.com