How update variable within another class - python

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

Related

Inheriting from multiple classes

class One:
def __init__(self):
self.one = 1
class Two:
def __init__(self):
self.two = 2
class Three(One, Two):
def __init__(self):
self.three = 3
super().__init__()
obj = Three()
print(obj.one)
print(obj.two)
print(obj.three)
i am currently self learning OOP, i am having a hard time understanding why the object was able to print the attribute from Class One but not also the one from Class Two despite me using the super function, the error raised is AttributeError: 'Three' object has no attribute 'two'. How do we inherit from multiple classes?
super().__init__() in Three will only refer to the first class in Method Resolution Order. In order to call all the __init__, you'd need to do super() in all of them:
class One:
def __init__(self):
self.one = 1
super().__init__()
class Two:
def __init__(self):
self.two = 2
super().__init__()
Or, if you don't want to / can't modify parent class signatures, you refer to the classes directly instead of using super, so they will all be called regardless of MRO:
class Three(One, Two):
def __init__(self):
self.three = 3
One.__init__()
Two.__init__()
class One:
def __init__(self):
self.one = 1
super().__init__()
class Two:
def __init__(self):
self.two = 2
super().__init__()
class Three(One,Two):
def __init__(self):
self.three = 3
super().__init__()
obj = Three()
print(obj.one)
print(obj.two)
print(obj.three)
use super().__init__method in every class.
if you dont want to use it. you can call init methods of class one and class two in init method of class three.

How can I call a class method on an instance within a different class __init__

I am creating a tic-tac-toe game in python. I'm trying to call the update method from my Board class on my boardState object within the class init of my Turn class.
When I run it I get NameError: name boardState is not defined.
class Board:
def __init__(self, player1 = "player1", player2 = "player2"):
self.p1 = player1
self.p2 = player2
self.matrix = MATRIX
self.winner = 'none'
self.available = getAvailable(self.matrix)
def update(self):
clear()
getAvailable(self.matrix)
self.show()
class Turn:
def __init__(self, sym):
self.sym = sym
boardState.update()
terminalState(boardState, self.sym, available)
print(f"{self.sym}'s turn:")
def main():
boardState = Board()
altTurns()
you are getting this error siense you haven't defined "boardState" before referencing it,
you need to set it to be a new Board Object before using it
class Board:
def __init__(self, player1 = "player1", player2 = "player2"):
self.p1 = player1
self.p2 = player2
self.matrix = MATRIX
self.winner = 'none'
self.available = getAvailable(self.matrix)
def update(self):
clear()
getAvailable(self.matrix)
self.show()
class Turn:
def __init__(self, sym):
self.sym = sym
boardState = Board() #the line I added
boardState.update()
terminalState(boardState, self.sym, available)
print(f"{self.sym}'s turn:")
this should fix your problem
If you want your Turn object to have access to the boardState object you've created in main() (and for main in turn to have access to the updated boardState), you should pass it in as a parameter to give all of the relevant functions access to it.
I assume the Turn is created by altTurns, so altTurns should itself take a board object that it can use to create the initial Turn.
class Turn:
def __init__(self, sym, boardState):
self.sym = sym
boardState.update()
terminalState(boardState, self.sym, available)
print(f"{self.sym}'s turn:")
def altTurns(boardState):
sym = None # or something?
turn = Turn(sym, boardState)
# more turns happen?
def main():
boardState = Board()
altTurns(boardState)
# our boardState has now been updated by Turn()

Unresolved attribute reference '...' for class '...'

When I call the render() method in the Zombie class, I want to add an instance of the Zombie object into ZombieList.list. When I try to do this, it says
Unresolved attribute reference list for class ZombieList.
Should I try to do this another way?
class ZombieList:
def __init__(self):
self.list = []
for zombie in self.list:
ds.blit(zombie.image, (1000, random.randint(10, 790)))
class Zombie(object):
def __init__(self):
self.attack = 3
self.speed = 5
self.health = 30
self.image = pygame.image.load("Assets/green zombie.png")
self.zombieList = []
def render(self):
ZombieList.list.append(self)
You've to create a ZombieList object, where you can append the Zombie objects to.
You can add a Class Objects to to the class Zombie:
class Zombie(object):
zombies = ZombieList()
def __init__(self):
self.attack = 3
self.speed = 5
self.health = 30
self.image = pygame.image.load("Assets/green zombie.png")
def render(self):
Zombie.zombies.list.append(self)
You cannot append to a list of a class. You need to append to an instance of a class. For instance:
class ZombieList:
def __init__(self):
self.list = []
for zombie in self.list:
ds.blit(zombie.image, (1000, random.randint(10, 790)))
my_zombie_list = ZombieList() # create an instance
class Zombie(object):
def __init__(self):
self.attack = 3
self.speed = 5
self.health = 30
self.image = pygame.image.load("Assets/green zombie.png")
self.zombieList = []
def render(self):
my_zombie_list.list.append(self) # refer to the previously created instance
There is no attribute list in ZombieList. Only once you've created a ZombieList through e.g. self.zombie_list = ZombieList() will you be able to make use of your list through self.zombie_list.list.
Even then, though, I imagine this probably isn't the design you're aiming for: I imagine that you don't want a ZombieList for each individual Zombie. Rather, whoever is initializing the Zombie objects should probably be in charge of maintaining the ZombieList instance as well.
You will also run into other issues. For example, the loop in
self.list = []
for zombie in self.list:
ds.blit(zombie.image, (1000, random.randint(10, 790)))
will never have any effect since self.list is always empty when that code is executed (since you've defined it to be empty on the previous line).

Class cross referencing?

I come from a C++ background and I am a bit lost without the whole pointer concept in python. Or at least it's unclear.
For instance, I want to create a game of tick tack toe using OOP in Python. I have a couple classes like so:
class Game(object):
def __init__(self, player1, player2):
self.board = [['','',''],
['','',''],
['','','']]
self.players = [player1, player2]
class Player(object):
def __init__(self, game, marking):
self.game = game
self.marking = marking # either 'X' or 'O'
It seems obvious that the game needs to have a reference to the two players and that a player is also part of a game, and should, therefore, have a reference to the game. However, the above code doesn't work because there is no way I can create a player without a creating a game first. But to create a game I need two players.
I could add in these references afterwards by doing something like: player.game = some_game_reference but this seems unpythonic and tedious to keep up with.
What is the best and most pythonic way of accomplishing this?
You can just have one class or the other updates its arguments. For example, create the players first, then have the game update the players with itself:
class Game(object):
def __init__(self, player1, player2):
self.board = [['','',''],
['','',''],
['','','']]
self.players = [player1, player2]
player1.game = self
player2.game = self
player1.marking = 'X'
player2.marking = 'O'
# Neither game nor marking make sense to set initially, until
# the players are added to a game.
class Player(object):
def __init__(self):
pass
p1 = Player()
p2 = Player()
g = Game(p1, p2)
(Whether you need this kind of coupling is, as others have pointed out, a separate design issue.)
Just to show the other direction is just as feasible:
class Player(object):
def __init__(self, game, marking):
self.game = game
self.marking = marking
game.players.append(self)
class Game(object):
def __init__(self):
self.board = [['','',''],
['','',''],
['','','']]
g = Game()
p1 = Player(g, 'X')
p2 = Player(g, 'O')
Hopefully, though, you'll agree that it makes more sense for the game to assign each player a marking. Here, you might try to add more than 2 players to a game, or add two X or two O players.

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