How would I use multiple classes together without inheritance? - python

I am currently learning classes and applying it as I go but I have come across an issue I am not sure how to get past:
I do not know how would I define a character having a weapon.
I have looked into the problem elsewhere but it always leads to inheritance which I want to avoid as it would not make sense. Is there any way to do this? I will be showing both the relevant code to the issue and then below, the full code for classes used.
Relevant Code
Weapon Class
class weapon:
def __init__ (self):
<constructor>
def set_attack (self, attack):
self.attack = attack
def get_attack (self):
return self.attack
Character Class
class character:
def __init__ (self):
<constructor>
def set_attack (self, amount):
self.attack = amount
def get_attack (self):
return self.attack
Full Code
Weapon Class
class weapon:
def __init__ (self, name, attack, crit_chance, crit_bonus, rarity, type_bonus):
self.name = name
self.attack = attack
self.crit_chance = crit_chance
self.crit_bonus = crit_bonus
self.rarity = rarity
self.type_bonus = type_bonus
def set_name (self, name):
self.name = name
def set_attack (self, attack):
self.attack = attack
def set_crit_chance (self, crit_chance):
self.crit_chance = crit_chance
def set_crit_bonus (self, crit_bonus):
self.crit_bonus = crit_bonus
def set_rarity (self, rarity):
self.rarity = rarity
def set_type_bonus (self, type_bonus):
self.type_bonus = type_bonus
def get_name (self):
return self.name
def get_attack (self):
return self.attack
def get_crit_chance (self):
return self.crit_chance
def get_crit_bonus (self):
return self.crit_bonus
def get_rarity (self):
return self.rarity
def get_type_bonus (self):
return self.type_bonus
Character Class
class character:
def __init__ (self, name, max_health, current_health, attack):
self.name = name
self.max_health = max_health
self.current_health = current_health
self.attack = attack
def set_name (self, name):
self.name = name
def set_max_health (self, amount):
self.max_amount = amount
def set_current_health (self, amount):
self.current_health = amount
def set_attack (self, amount):
self.attack = amount
def get_name (self):
return self.name
def get_max_health (self):
return self.max_health
def get_current_health (self):
return self.current_health
def get_attack (self):
return self.attack
Player Class Inheriting From Character Class
class player (character):
def __init__ (self, name, max_health, current_health, attack, money, level, xp):
super().__init__(name, max_health, current_health, attack)
self.money = money
self.level = level
self.xp = xp
def set_money (self, amount):
self.money = amount
def set_level (self, amount):
self.level = amount
def set_xp (self, amount):
self.xp = amount
def get_money (self):
return self.money
def get_level (self):
return self.level
def get_xp (self):
return self.xp
I am expecting the player, which inherits from character, to be able to attack using the value of a weapon object tied to that character.
Any info is appreciated.emphasized text

To begin with you can get rid of all those getters and setters and make your classes as
class Weapon:
def __init__ (self, name, attack, crit_chance, crit_bonus, rarity, type_bonus):
self.name = name
self.attack = attack
self.crit_chance = crit_chance
self.crit_bonus = crit_bonus
self.rarity = rarity
self.type_bonus = type_bonus
class Character:
def __init__ (self, name, max_health, current_health, attack):
self.name = name
self.max_health = max_health
self.current_health = current_health
self.attack = attack
Then pass a weapon object to your player class, and use that to attack the player, here weapon represents the Weapon with the player
class Player (character):
def __init__ (self, name, max_health, current_health, attack, money, level, xp, weapon):
super().__init__(name, max_health, current_health, attack)
self.money = money
self.level = level
self.xp = xp
self.weapon = weapon
#For e.g. A weapon attacks and reduces the current health of the player
def attack(self):
self.current_health -= self.weapon.attack
Or pass both a weapon and character class object to your player class, otherplayer is the Player attacked, and weapon is the Weapon with the player
class Player (character):
def __init__ (self, name, max_health, current_health, attack, money, level, xp, otherplayer, weapon):
super().__init__(name, max_health, current_health, attack)
self.money = money
self.level = level
self.xp = xp
self.otherplayer = otherplayer
self.weapon = weapon
def attack(self):
self.otherplayer.current_health -= self.weapon.attack

The Character class would have a field that's an instance of the Weapon class, like this:
class Character:
def __init__ (self, name, max_health, current_health, attack, weapon):
self.name = name
self.max_health = max_health
self.current_health = current_health
self.attack = attack
self.weapon = weapon # this line
def set_name(self, name):
self.name = name
def set_weapon(self, weapon):
self.weapon = weapon
You'd just build a Weapon object and pass it to the Character object when constructing it (or via the setter method):
weapon = Weapon()
character = Character('Char Name', 100, 100, 20, weapon)
Now, as a side note, please name your classes using uppercase for the initial letter, it's a PEP8 convention. It helps differentiating class names from instances, otherwise you wouldn't be able to call the instances weapon and character in my example above.

Related

How update variable within another class

I have these classes :
class Game():
def __init__(self):
self.player = Player("name")
class Turn():
def __init__(self):
pass
def end(self):
#how update xp player
class Player():
def __init__(self, name):
self.name = name
self.xp = 0
And my question is how when turn is terminated, how update the player
If these classes are in the same module you can define a global variable in the module that can be used in both classes. Otherwise you need to explicitly pass the variable on the instances of both classes.
Your Game class appears to have a reference to a player in its self.player attribute. If you want to update that player's xp attribute, you can do something like this:
def end(self):
self.player.xp += 5

How do I add arguments to a subclass in Python 3

class Wolf:
def __init__(self, legs):
self.legs = 4
class Dog(Wolf):
def __init__(self, color):
self.color = color
fido = Dog(legs = 4, color = "brown")
This would spute out an error message. How would I do something like that where I add parameters to the subclass that doesn't pertain to the superclass.
Try this:
class Wolf:
def __init__(self, legs):
self.legs = 4
class Dog(Wolf):
def __init__(self, legs, color):
super().__init__(legs)
self.color = color
fido = Dog(legs=4, color="brown")
That's not how inheritance works. When you inherit from another class, the super-class's parameters are not automatically added to the sub-class's parameter list. You must explicitly accept the desired parameters in your sub-class's constructor and pass them on to the super class's constructor:
class Wolf:
def __init__(self, legs):
self.legs = 4
class Dog(Wolf):
def __init__(self, color, legs):
super().__init__(legs)
self.color = color
fido = Dog(legs = 4, color = "brown")
Here's an example from a tutorial which explains inheritance and shows how to do this. You need to call the parent class's init function as in this similar example from this tutorial:
class Pet(object):
def __init__(self, name, species):
self.name = name
self.species = species
def getName(self):
return self.name
def getSpecies(self):
return self.species
def __str__(self):
return "%s is a %s" % (self.name, self.species)
class Dog(Pet):
def __init__(self, name, chases_cats):
Pet.__init__(self, name, "Dog")
self.chases_cats = chases_cats
def chasesCats(self):
return self.chases_cats
You still have to pass in the legs argument for Dog, and then use super:
class Wolf:
def __init__(self, legs):
self.legs = 4
class Dog(Wolf):
def __init__(self, color, legs):
super().__init__(legs)
self.color = color
fido = Dog(legs = 4, color = "brown")

Python inherit variables from parent class

Sorry if I don't explain it that well but I'll try my best:
So I want to inherit the variables from the Parent class, but I don't want to pass them again when creating an instance of the Child class because I think that is redundant. I just want to use the eye color from the Parent for example. See the example code below for what I mean
This is what works:
class Parent:
def __init__(self, eye_color, length):
self.eye_color = str(eye_color)
self.length = length
class Child(Parent):
def __init__(self, gender, eye_color, length):
super().__init__(eye_color, length)
self.gender = str(gender)
x = Parent("Blue", 2)
y = Child("Men", "Blue", 2)
print(x.eye_color, x.length)
print(y.gender, x.length)
This is what I somehow want:
class Parent:
def __init__(self, eye_color, length):
self.eye_color = str(eye_color)
self.length = length
class Child(Parent):
def __init__(self, gender):
super().__init__(eye_color, length)
self.gender = str(gender)
x = Parent("Blue", 2)
y = Child("Men")
print(x.length, x.eye_color)
print(y.gender, x.length)
What you ask does not make sense:
class Parent:
def __init__(self, eye_color, length):
self.eye_color = str(eye_color)
self.length = length
class Child(Parent):
def __init__(self, gender):
super().__init__(eye_color, length)
self.gender = str(gender)
x = Parent("Blue", 2)
y = Child("Men")
print(x.length, x.eye_color)
print(y.gender, x.length)
In child, the parameters eye_color and length come from nowhere.
rassar example is good if you want to reuse a parent object.
You can also do the following:
class Parent:
# def __init__(self, eye_color=(default value here), length=(default value here)):
def __init__(self, eye_color="", length=0):
self.eye_color = str(eye_color)
self.length = length
OR
class Parent:
def __init__(self, eye_color="", length=0):
self.eye_color = str(eye_color)
self.length = length
class Child(Parent):
def __init__(self, gender, *args, **kwargs):
super().__init__(*args, **kwargs)
self.gender = str(gender)
x = Parent("Blue", 2)
y = Child("Men") # Work with first example of Parent
y = Child("Men", eye_color="Blue", length=2) # Work with first
y = Child("Men", "Blue", 2) # Work with second example
print(x.length, x.eye_color)
print(y.gender, y.length)
You could try passing a Parent instance to the Child initializer...That's probably the closest you'll get.
class Parent:
def __init__(self, eye_color, length):
self.eye_color = str(eye_color)
self.length = length
class Child(Parent):
def __init__(self, gender, parent):
super().__init__(parent.eye_color, parent.length)
self.gender = str(gender)
x = Parent("Blue", 2)
y = Child("Men", x)
print(x.length, x.eye_color)
print(y.gender, x.length)
Another thing you could do is hold a last_parent variable:
global last_parent
class Parent:
def __init__(self, eye_color, length):
self.eye_color = str(eye_color)
self.length = length
last_parent = self
class Child(Parent):
def __init__(self, gender):
super().__init__(last_parent.eye_color, last_parent.length)
self.gender = str(gender)
x = Parent("Blue", 2)
y = Child("Men")
print(x.length, x.eye_color)
print(y.gender, x.length)

How to use variables from one class in another class

I know this question has been asked before but for the life of me I can't seem to understand the answers so I'm here asking for some help with an example. I am not trying to waste anybodies time here so please don't internet yell at me!
I have a class called Enemy with variables. How do I access these variables in another class?
Heres my example.
import tkinter
from tkinter import ttk
class Enemy(object):
def __init__ (self, name, attack, defence, gold, health, experience):
self.name = name
self.attack = attack
self.defence = defence
self.gold = gold
self.health = health
self.experience = experience
Enemy1 = Enemy("Enemy Soldier", "5", "1", "10", "10", "30")
class Application(object):
def __init__(self):
self.enemyLabel = tkinter.Label(text= self.Enemy1.name)
self.enemyLabel.pack()
myApp = Application()
myApp.root.mainloop()
This is a very narrowed down version of my code.
You have to define enemy1 in the scope of Application.__init__:
class Enemy(object):
def init (self, name, attack, defence, gold, health, experience):
self.name = name
self.attack = attack
self.defence = defence
self.gold = gold
self.health = health
self.experience = experience
class Application(object):
def __init__(self):
self.enemy1 = Enemy("Enemy Soldier", "5", "1", "10", "10", "30")
self.enemyLabel = tkinter.Label(text=self.enemy1.name)
self.enemyLabel.pack()
Anywhere within the scope of where you created Enemy1, you can simply use Enemy1.name, Enemy1.attack, etc.

How to determinate whose turn is? Card game (tkinter)

I'm making Palace card game with 4 players, I'm not sure how should I determinate whose on turn for throwing a card? Should I use smoething like counter or what ?
Use a simple counter modulo the number of players.
class Game(object):
def __init__(self):
self.count = 4
self.current_player = 0
def next_turn(self):
self.current_player += 1
self.current_player %= self.count
Since different cards may lead to different players having the next turn, and to the game switching between going clockwise and counterclockwise, I suggest you leave the decision to the card object.
from abc import ABCMeta, abstractmethod
class Card(object):
__metaclass__ = ABCMeta
def __init__(self, color, value):
"""
Color is either "r", "b", "g", or "y". Value is 0-9.
"""
self.color = color
self.value = value
def is_valid(self, color, value=None):
return color in self.color or value == self.value
#abstractmethod
def card_effect(self, game):
pass
This base class for all cards is the "contract" that a class has to fulfill to be considered a card. Since we're not planning on instantiating this class we make it an abstract class.
class Normal(Card):
def card_effect(self, game):
game.increment_player_index(1)
class Skip(Card):
def __init__(self, color):
super(Skip, self).__init__(color, "skip")
def card_effect(self, game):
game.increment_player_index(2)
class Turn(Card):
def __init__(self, color):
super(Turn, self).__init__(color, "turn")
def card_effect(self, game):
game.toggle_direction()
game.increment_player_index(2)
class PlusTwo(Card):
def __init__(self, color):
super(PlusTwo, self).__init__(color, "+2")
def card_effect(self, game):
game.increment_player_index(1)
game.current_player().punish(2)
game.increment_player_index(1)
For the black cards we do it like this:
class PlusFour(Card):
def __init__(self):
super(PlusFour, self).__init__("rbgy", "+4")
def card_effect(self, game):
color = game.current_player().choose_color()
game.set_color(color)
game.increment_player_index(1)
game.current_player().punish(4)
game.increment_player_index(1)

Categories