How can the attributes of one class be accessed in another? - python

So what am I trying to do
Well what I'm doing is trying to create a battling system between your character and an enemy
So wheres it going wrong
Well there are two classes:
class Ally
and
class Enemy
Each class has their own unique attributes of name, health, attack and defense
class Ally
def __init__(self, name, health, attack, defense):
self.name = 'goodguy'
self.health = 100
self.attack = 50
self.defense = 30
class Enemy
def __init__(self, name, health, attack, defense):
self.name = 'badguy'
self.health = 120
self.attack = 40
self.defense = 20
But both class Ally and class Enemy need each others health and defense attributes inorder to do damage
class Ally(object):
def __init__(self, name, health, attack, defense):
self.name = goodguy
self.health = 100
self.attack = 50
self.defense = 30
def fight(self)
(damage moves)
Enemy health = Enemy.health - ((self.attack/Enemy.defense)+2)
def battle_script(self)
while self.health > 0 and Enemy.health > 0:
self.fight()
if Enemy.health <=0:
break
Enemy.fight()
if self.health <=0:
break
if Enemy.health() <= 0:
print ('The ' + Enemy.name + ' was defeated')
if self.health <= 0:
print ("You were defeated")
class Enemy(object):
def __init__(self, name, health, attack, defense):
self.name = badguy
self.health = 120
self.attack = 40
self.defense = 20
def fight(self)
(random damage moves)
Enemy health = Ally.health - ((self.attack/Ally.defense)+2)
Ally.battle_scrip()
So the problem is that I don't know how to pull in their respective attributes, i.e. in the battle script calling in the Enemy.health, I could probably pull it all into one class, but I'd rather keep them separated for when I create more enemies.

first you create instances of your class bob = Ally();evil_frank = Enemy(); ... beyond that I have no idea what you expect to happen here based on the code you are given but im guessing you want something like what follows
def fight(ally,enemy):
while ally.is_alive() and enemy.is_alive():
ally.hp -= enemy.dmg
enemy.hp -= ally.dmg
print "OK FIGHT OVER SOMEONE DIED..."
fight(bob,evil_frank)

So you want a one:many relationship for the Ally:Enemy classes? What I would do, is create a list of enemy class objects that are a member of your Ally class. You could even pass in an argument to your Ally constructor to pick the number of enemies you want.
Should be something like this:
import itertools
class Ally(object):
def __init__(self, enemies):
self.name = goodguy
self.health = 100
self.attack = 50
self.defense = 30
self.enemies = []
for _ in itertools.repeat(None, enemies):
self.enemies.append(Enemy())
...
If you want a Many:Many relationship I would create another class that can be an object for the battle. Lets call this the "Battle" class. You can then do the same trick of having a list of class objects for both your allies and enemies and then have your logic for conducting the battle in the battle class.
class Battle(object):
def __init__(self, allies, enemies):
self.allies = []
self.enemies = []
for _ in itertools.repeat(None, allies):
self.allies.append(Ally())
for _ in itertools.repeat(None, enemies):
self.enemies.append(Enemy())
...

Related

Some questions regarding __init_ errors in python

I got the error : TypeError: init() missing 1 required positional argument: 'attack'
class Unit:
def __init__(self, name):
self.name = name
class Power(Unit):
def __init__(self, name, attack):
Unit.__init__(self, name)
self.attack = attack
supatt = attack * 2
print("{0} has a power of {1} and it can develop {1}
of its superpowers".format(self.name, attack, supatt))
class Ground(Power):
def __init__(self, name, attack, velocity, friction):
Power.__init__(self, attack)
self.velocity = velocity
self.friction = friction
totalv = velocity - fiction
print("{0} : Groud Attack. \nTotal Speed : {1}.\n
Power : {2}.".format(self.name, totalv, attack))
class Sky(Power):
def __init__(self, name, attack, skyspeed, airres):
Power.__init__(self, attack)
self.skyspeed = skyspeed
self.airres = airres
totalss = skyspeed - airres
print("{0} : Sky Attack. \nTotal Speed : {1}.\n Power
: {2}.".format(self.name, totalss, attack))
valkyrie = Sky("Valkyrie", 200, 300, 150)
print(valkyrie)
The error comes in the Sky(Power) class where I wrote :
Power.__init__(self, attack)
I thought I already wrote attack here. What is wrong with this code?
You were trying to inherit the Power Class to every other class except for the Unit class.
You want to inherit the classes using the super() function.
class Unit:
def __init__(self, name):
self.name = name
class Power(Unit):
def __init__(self, name, attack):
Unit.__init__(self, name)
self.attack = attack
supatt = attack * 2
print("{0} has a power of {1} and it can develop {1} of its
superpowers".format(self.name, attack, supatt))
class Sky(Power):
def __init__(self, name, attack, skyspeed, airres):
super().__init__(self, attack)
self.skyspeed = skyspeed
self.airres = airres
totalss = skyspeed - airres
print("{0} : Sky Attack. \nTotal Speed : {1}.\n Power:
{2}.".format(self.name, totalss, attack))
class Ground(Power):
def __init__(self, name, attack, velocity, friction):
super().__init__(self, attack)
self.velocity = velocity
self.friction = friction
totalv = velocity - friction
print("{0} : Groud Attack. \nTotal Speed : {1}.\nPower :
{2}.".format(self.name, totalv, attack))
valkyrie = Sky("Valkyrie", 200, 300, 150)
print(valkyrie)

Having difficulty understanding Python OOP

I'm fairly green to OOP and I was just playing around with it in Python and came across something I can't explain so hopefully you guys will be able to help.
I was playing with the code below:
class Car():
def __init__(self, brand, model, speed):
self.brand = brand
self.model = model
self.speed = speed
def increase_speed(self):
return self.speed + 1
def decrease_speed(self, decrease_by):
return self.speed - decrease_by
car1 = Car("tesla","x",30)
print(car1.brand)
print(car1.speed)
print(car1.increase_speed())
print(car1.speed)
print(car1.decrease_speed(10))
My question is, I am expecting after increasing the speed, car1's speed will be 31 but instead it prints out 30. Why is it that way and how should the code be written for the speed to be 31 instead?
def increase_speed(self):
self.speed += 1
return self.speed
Previously you did not increase your speed, rather you just return a value that is equal to the speed plus 1. Similarly, change your decrease_speed function.
Instead of returning the values, set them on the attributes:
class Car():
def __init__(self, brand, model, speed):
self.brand = brand
self.model = model
self.speed = speed
def increase_speed(self):
self.speed = self.speed + 1
def decrease_speed(self, decrease_by):
self.speed = self.speed - decrease_by
I deliberately don't return the changed speed anymore, as it's good style (at least with methods mainly setting attributes) to either return something or change state:
car1 = Car("tesla","x",30)
print(car1.brand)
print(car1.speed)
car1.increase_speed()
print(car1.speed)
car1.decrease_speed(10)
print(car1.speed)
The method increase_speed is just returning self.speed + 1, if you wish to update the speed you need to self.speed = self.speed + 1 into the method increase speed.

[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

positional argument OSX

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):

Fixing class method loop

I've encountered a problem with my class file and I can't seem to find a fix around it. I was hoping someone could point me to the right direction.
Here's my code:
class Car:
def __init__(self, year_model, make, speed):
self.__year_model = year_model
self.__make = make
self.__speed = 0
def set_year_model(self, year_model):
self.__year_model = year_model
def set_make(self, make):
self.__make = make
def get_year_model(self):
return self.__year_model
def get_make(self):
return self.__make
def accelerate(self):
self.__speed + 5
return self.__speed
def decelerate(self):
self.__speed - 5
return self.__speed
def get_speed(self):
return self.__speed
Essentially, I want the speed attribute set to 0, and have 3 methods (accelerate, decelerate, and get_speed) which add and subtract 5 to the speed attribute and eventually return the speed attribute so it can be printed.
I would guess there's a problem with my formatting but I can't seem to find the correct arrangement that would fix the class.
The real program is suppose to loop the accelerate method 5 times, but the class method is supposed to handle the sequential addition and return the final speed.
import car
user_year = 1995
user_make = "toyota"
user_speed = 0
user_car = car.Car(user_year, user_make, user_speed)
for count in range(1,6):
user_car.accelerate()
print user_car.get_speed()
I know this code is very weak, but it's all makeshift to help make my problem clearer.
So hopefully it's not too confusing and I can get an answer.
self._speed + 5 computes the current speed plus 5. But you're not actually storing the computed value anywhere. You want to use self._speed = self._speed + 5, or the more commonly used form, self._speed += 5.
The problem is, of course, the "+=" and "-=" portions that are missing, but I'd go a step further and suggest that if you're writing new python code, you become familiar with new style classes. In a new style class, your code could be written as follows:
class Car(object):
def __init__(self, year_model, make, speed):
self.year_model = year_model
self.make = make
self.speed = 0
def __set_year_model(self, year_model):
self.__year_model = year_model
def __set_make(self, make):
self.__make = make
def __set_speed(self, speed):
self.__speed = speed
def __get_year_model(self):
return self.__year_model
def __get_make(self):
return self.__make
def accelerate(self):
self.speed += 5
def decelerate(self):
self.speed -= 5
def __get_speed(self):
return self.__speed
speed = property(fget=__get_speed,fset=__set_speed,fdoc="Set or Retrieve the current speed of this instance of the Car object")
make = property(fget=__get_make,fset=__set_make,fdoc="Set or Retrieve the make of this instance of the Car object")
year_model = property(fget=__get_year_model,fset=__set_year_model,fdoc="Set or Retrieve the Year and Model of this instance of the Car object")
In addition, the code changes in the main file:
import car
user_year = 1995
user_make = "toyota"
user_speed = 0
user_car = car.Car(user_year, user_make, user_speed)
for count in range(1,6):
user_car.accelerate()
print user_car.speed

Categories