Python Class. One def get for several attribute - python

I need help to be more clear how to make my code correctly. Now it's work but I still think the code logic not correct :)
I have one class with several attributes:
class Game:
def __init__(self, player1, player2, player3, player4, score_pair1, score_pair2):
self.player1 = player1
self.player2 = player2
self.player3 = player3
self.player4 = player4
self.score_pair1 = score_pair1
self.score_pair2 = score_pair2
self.Online_Players_Dict = []
self.Temp_Players_Dict = []
self.Temp_import_players = []
I have method inside of this class for work with all attributes:
def create_temp_players(self):
for i in ('player1', 'player2', 'player3', 'player4'):
temp = self.__getattribute__(i)
if not isinstance(temp, Player):
for ii in self.Temp_import_players:
if ii['name'] == self.__getattribute__(i):
self.__setattr__(i, Player(self.__getattribute__(i), ii['score'], ii['daily_score']))
b = self.__getattribute__(i)
a = dict(name=b.name, score=b.score, daily_score=b.daily_score)
self.Online_Players_Dict.append(a)
temp = self.__getattribute__(i)
if not isinstance(temp, Player):
self.__setattr__(i, Player(self.__getattribute__(i)))
b = self.__getattribute__(i)
a = dict(name=b.name, score=b.score, daily_score=b.daily_score)
self.Online_Players_Dict.append(a)
self.Temp_Players_Dict.append(a)
And everything work correct, but I think not right to use (getattribute) and (setattr) here. But I can't find other way to correct interaction attributes in the code.
Do you have any idea how to make it better?
PS: Class Player also has attribute:
class Player:
def __init__(self, name, score=500, daily_score=0):
self.name = name
self.score = score
self.daily_score = daily_score

I changed code like this
for player, i in zip(self.players, (0, 1, 2, 3)):
if not isinstance(self.players[i], Player):
for ii in self.Temp_import_players:
if ii['name'] == self.players[i]:
self.players[i] = Player(self.players[i], ii['score'], ii['daily_score'])
a = dict(name=self.players[i].name, score=self.players[i].score, daily_score=self.players[i].daily_score)
self.Online_Players_Dict.append(a)
if not isinstance(self.players[i], Player):
self.players[i] = Player(self.players[i])
a = dict(name=self.players[i].name, score=self.players[i].score, daily_score=self.players[i].daily_score)
self.Online_Players_Dict.append(a)
self.Temp_Players_Dict.append(a)
Later will refactoring all self.playerX to self.player[X]

Related

how's i can calling to int from def in class?

i have this code:
class PLAYER:
def player_move(self):
if self.new_block == True:
body_copy = self.body[:]
body_copy.insert(0,body_copy[0] + self.direction)
self.body = body_copy[:]
self.new_block = False
self.score += 1
#print(self.score)
i want to calling self.score from outside the PLAYER class
You need to add a constructor (the init method) as done below, and within the constructor you must define self.score, as well as all the other fields you want your PLAYER class to have. In the code below I am assuming that when you are initializing a PLAYER object that you are providing the new_block, direction, and body information, however you defined these fields, which is unclear from the question.
class PLAYER:
def __init__(self, new_block,direction,body):
self.score = 0
self.new_block = new_block
self.direction = direction
self.body = body
def player_move(self):
if self.new_block == True:
body_copy = self.body[:]
body_copy.insert(0,body_copy[0] + self.direction)
self.body = body_copy[:]
self.new_block = False
self.score += 1

automatically instantiating objects

players_list = [Ani, Paty, Felix, Alex]
class Player:
def __init__(self, name):
self.name = name
self.score = 0
self.vote = 0
self.player_hand = []
self.choice = ''
self.player_hand = []
def player_turn(self):
print(self.name, "'s turn")
def p_vote(self):
print(self.name, " voted")
I tried to iterate over the list, but it always gives me an error: NameError: name 'Ani' is not defined
for player in players_list:
player = Player(str(player))
But doing all the process manually work:
Ani = Player("Ani"), etc
Is there any way that i can automate this process?
First of all the thing you should know, the players_list that you have declared are not containing strings, they are being considered as variables which you have not defined anywhere, and therefore the NameError.
Now, if you want to correct this, and if you actually intend to store objects of Player in players_list, then you can do the following:
players_list = ["Ani", "Paty", "Felix", "Alex"]
class Player:
def __init__(self, name):
self.name = name
self.score = 0
self.vote = 0
self.player_hand = []
self.choice = ''
self.player_hand = []
def player_turn(self):
print(self.name, "'s turn")
def p_vote(self):
print(self.name, " voted")
for i in range(len(players_list)):
players_list[i]=Player(players_list[i])
This will store Player objects in the list you have declared just the thing that you expect to get.
You are having problems with the players not being defined. So players_list = [Ani, Paty, Felix, Alex] will throw an error because the objects Ani, Paty, Felizx, and Alex do not exist.
class Player:
def __init__(self, name):
self.name = name
self.score = 0
self.vote = 0
self.player_hand = []
self.choice = ''
self.player_hand = []
def player_turn(self):
print(self.name, "'s turn")
def p_vote(self):
print(self.name, " voted")
Now, we need to iterate through the list.
players_list = ['Ani', 'Paty', 'Felix', 'Alex']
players = [Player(player) for player in players_list]
Sounds like you're trying to dynamically create variables - write code that writes code.
You could try to use the exec built-in function.
players = ['Ani', 'Paty', 'Felix', 'Alex']
class Player:
def __init__(self, name):
self.name = name
def p_vote(self):
print(self.name + " voted.")
for player in players:
exec( "%s = Player( '%s' )" %(player, player) )
Ani.p_vote()
Although, general internet advice has two points to make:
Be cautious where you use exec.
The Pythonic way is to write out the variables, "explicit is better than implicit."

How to change instance variable when another related instance variable is changed in a class?

I recently try to code a text based game. I want to change player proficiency when player level up. How should I change my code for this?
class Player:
def __init__(self,name,_class,_race):
self.name = name
self.level = 1
self.proficiency = (int(self.level/3)+1)*2
self.inventory = 0
self.skills = returnSkills()
self.stats = returnStats()
self._class = _class
self._race = _race
self.exp = 0
def levelUp(self):
self.level+=1
newPlayer = Player("Player","Barbarian","Human")
print(newPlayer.level)
for i in range(10):
print(newPlayer.level)
print(newPlayer.proficiency)
newPlayer.levelUp()
You can recalculate the proficiency attribute directly in the levelUp() function. Once you have updated the level attribute, that new value of level will be used to calculate the new proficiency.
def levelUp(self):
self.level+=1
self.proficiency = (int(self.level/3)+1)*2
You could make proficiency a property, so it is calculated from the current level each time it is referenced.
class Player:
def __init__(self,name,_class,_race):
self.name = name
self.level = 1
self.inventory = 0
self.skills = returnSkills()
self.stats = returnStats()
self._class = _class
self._race = _race
self.exp = 0
#property
def proficiency(self):
return (int(self.level/3)+1)*2
...
or you could leave it as a plain attribute, and recalculate it inside your levelUp method.

Competition registration program using classes

I have an assignment to create a code that would define 2 classes, a player and a team each of these having some parameters. Player is supposed to have a name, a number of skis, a number of sledges and a player index(number of games played by the player before).
I managed to define these attributes of the class but I'm having a hard time implementing the team class. Team is supposed to hold the name of the team and the number of players-the players cannot be just their names it must link to the class instance(player). I don't understand how to use the information provided in the player instance to implement team. Here's my code so far:
class Player:
def __init__(self, name, skis, index):
self.name = name
self.sledges = []
self.skis = []
self.index = index
pass
class Team:
def __init__(self, name, players):
self.name = name
self.players = [Player]
pass
def get_players_count()
def get_transport_capacity()
def get_average_index()
*Update
Thank you for your help, I have one more function to add, a function that would return the number of passengers a team could accommodate. I've tried something like this but I don't think the syntax is correct. The user inputs the number of places in each sledge so I need to iterate over the values in the list to get the number of places.
def get_transport_capacity(self):
skis = len(Player.skis)
for i in Player.sledges:
sledges += Player.sledges[i]
capacity = skis + sledges
return capacity
class Player:
def __init__(self, name, index):
self.name = name
self.sledges = []
self.skis = []
self.index = index
class Team:
def __init__(self, name, players):
self.name = name
self.players = players
def get_players_count(self):
return len(self.players)
def add_player(self, player):
self.players.append(player)
def get_average_index(self):
indexes = sum(list(map(lambda p: p.index, self.players)))
count = self.get_players_count()
return float(indexes) / count
Usage:
a = Player('AName', 2)
b = Player('BName', 11)
team = Team('TeamName', [a, b])
instead of
self.players = [Player]
why not:
self.players = []
And then have a method to add players to the team as in:
def add_player(self, player):
# ensure optionally that player is a PLayer instance
assert type(player) == Player
self.players += player

Ping Pong simulation not correctly triggering function

I'm new to OOP and am practicing putting together a little bit more complex programs using various classes and implementing principles like Inheritance. I've created a Ping-Pong simulation that has a Player class which contains the probability that the player will win their serve. Then I have a PingPong class which is a subclass of the super class RacquetSports. Each instance is a single game, with the ability to change server, and record who won, and whether or not it was a shut-out. Finally, I have a SimStats class whose purpose is to record the stats across "n" number of games.
My problem is that it seems like my play_game function is not correctly firing, when I place a print statement in there it never triggers. My current result when running the whole program is that Player1 has 10 wins no shutouts, and Player2 has zero of both.
Finally, any suggestions on better OO practice would also be appreciated. Here is my player class:
from random import random
class Player(object):
def __init__(self, prob_win):
self.prob = prob_win
self.points = 0
def wins_serve(self):
return self.prob >= random()
def add_point(self):
self.points += 1
def get_score(self):
return self.points
My RacquetSports class:
from abc import ABCMeta, abstractmethod
from player import Player
class RacquetSport(object):
__metaclass__ = ABCMeta
def __init__(self, prob1, prob2):
self.player1 = Player(prob1)
self.player2 = Player(prob2)
self.server = self.player1
def play_game(self):
while not self.game_over():
self.sim_point()
#abstractmethod
def type(self):
pass
def chg_server(self):
if self.server == self.player1:
self.server = self.player2
else:
self.server = self.player1
def sim_point(self):
if self.server.wins_serve():
self.server.add_point()
else:
self.chg_server()
#abstractmethod
def game_over(self):
pass
def get_scores(self):
return self.player1.get_score(), \
self.player2.get_score()
def return_stats(self):
p1_score, p2_score = self.get_scores()
print(p1_score, p2_score)
won = 'p1'
if p2_score > p1_score:
won = 'p2'
return won, self.__shutout(p1_score, p2_score)
#staticmethod
#abstractmethod
def __shutout(score1, score2):
pass
My PingPong and SimStats classes, as well as my calling code:
from racquet import RacquetSport
class PingPong(RacquetSport):
def type(self):
return 'Ping Pong'
def game_over(self):
return self.player1.get_score == 11 or \
self.player2.get_score == 11
#staticmethod
def __shutout(score1, score2):
return abs(score1 - score2) == 11
class SimStats(object):
def __init__(self):
# First field is games won, second is shutouts.
self.gms_won_p1 = [0] * 2
self.gms_won_p2 = [0] * 2
def update(self, game):
won, shutout = game.return_stats()
if won == 'p1':
self.gms_won_p1[0] += 1
if shutout:
self.gms_won_p1[1] += 1
else:
self.gms_won_p2[0] += 1
if shutout:
self.gms_won_p2[1] += 1
def print_results(self):
tot_games = self.gms_won_p1 + self.gms_won_p2
print('Wins for Player 1 = {} Shutouts = {}\n'
'Wins for Player 2 = {} Shutouts = {}'.format(*tot_games))
if __name__ == '__main__':
stats = SimStats()
for x in range(1, 11):
game = PingPong(.5, .5)
stats.update(game)
stats.print_results()
Your first problem is that you never call play_game. My guess is that you intend it to work like this:
if __name__ == '__main__':
stats = SimStats()
for x in range(1, 11):
game = PingPong(.5, .5)
game.play_game()
stats.update(game)
stats.print_results()
Next, you have a bug that will cause the entire game to last forever. Take a look at these lines:
def game_over(self):
return self.player1.get_score == 11 or \
self.player2.get_score == 11
get_score is a function, so you need to call it:
def game_over(self):
return self.player1.get_score() == 11 or \
self.player2.get_score() == 11

Categories

Resources