How can I automate the creation of instances of a class? - python

So in python 3 I am having trouble creating multiple instances of a class automatically. I am trying to make monopoly and here is the code sample that is giving me problems.
def numplayer():
numplayer = int(input('How many players would you like? (up to four)'))
while numplayer > 4 or numplayer < 1:
numplayer = int(input('How many players would you like? (up to
four)'))
for i in range(numplayer):
PlayerMoney.append(1500)
What I want to do is also add something that will create the number of players that numplayers equals to in the for i in range(numplayer) function. I have the player as a class but I don't want to manually create every single class for every player. If there is a solution to this, please do tell. Thanks!
EDIT: So I think this might be bad wording in the title but I'm trying to create multiple instances of a single class (the player).
Here is the code for the player class:
class Player:
def __init__(self, name, money, position):
self.name = name
self.money = money
self.position = position
def DiceRoll(self):
x = random.randint(1, 6)
y = random.randint(1, 6)
sum = x + y
return [sum, x, y]
def getName(self):
return sef.name
def getMoney(self):
return self.money
def getPosition(self):
return self.position

# Create Class
class Player:
def greating(self):
print 'Hello!'
# List to store instanses
l = []
for i in range(4):
l.append(Player())
# Call Instance #1 methods
l[0].greating()
Here we have a player class and 4 instances from this class stored in l list.

I would advise you structure your code as below. It's usually a good idea for your function to return something.
def setup():
n = int(input('How many players would you like? (up to 4)'))
names = [input('Give name #{0}'.format(i)) for i in range(1, n+1)]
return [Player(name, 1500, 0) for name in names]
players = setup()

Related

In Python, do we need to keep track of dynamically-declared instances?

One thing that I am struggling with while trying to learn concepts of OOP is creation of class instances. Most of the tutorials online will explain basic principles like Init, Self, Inheritance etc.. but when it comes to creating instances of the class itself it is usually reduced to something like that:
emp1 = Employee("John")
emp2 = Employee("Leviticus")
In reality most of us beginners will want to create instance of a class dynamically (On press of button etc..) not directly in code and also will be interessted in keeping track of our instances. What I was able to come up is this:
from tkinter import *
import random
class Point:
_registry = []
def __init__(self, x_pos, y_pos):
self._registry.append(self)
self.x_pos = x_pos
self.y_pos = y_pos
print(self.x_pos, self.y_pos)
def create_point():
Point(random.randint(1,20),random.randint(1,20))
window = Tk()
button = Button(window, text = "Add point", command=create_point)
button.pack()
window.mainloop()
Can someone advise if this is a proper way to do this? Shouldnt the fnction create_point be within Point class? What is the proper way to keep track of instances and later delete them? Shall I use some sort of ID attribute to keep track and "itemize" my instances? Is there any good source with tutorial that deals with that?
Thank you
Jacob
after completing tutorial at: https://pythonschool.net/category/oop.html I managed to get what I wanted by doing:
class Point:
def __init__(self,ID, xcor, ycor):
self._ID = ID
self._xcor = xcor
self._ycor = ycor
def report(self):
return {"ID:":self._ID,"xcor":self._xcor,"ycor":self._ycor}
def get_ID(self):
return self._ID
class Points:
def __init__(self):
self._points = []
def add_point(self, point):
self._points.append(point)
def return_index_from_ID(self, ID):
for i, o in enumerate(self._points):
if o.get_ID() == ID:
break
return i
def delete_point(self, index):
del self._points[index]
def print_contents(self):
for x in self._points:
print(x.report())
def return_empty_ID(self):
list = []
for x in self._points:
list.append(x.get_ID())
if not list:
return 1
else:
for i in range(1, max(list)+2):
if i not in list: break
return i
def add_point( xcor, ycor, points):
points.add_point(Point(points.return_empty_ID(), xcor, ycor))
def delete_point(ID, points):
points.delete_point(ID)
Simple main function for testing to show what I was after:
from point_class import *
myPoints = Points()
noexit = True
while noexit:
print("**********************************************")
print("0 - Exit")
print("1 - Add Point")
print("2 - Print Points")
print("3 - Delete Points")
print("**********************************************")
choice = int(input("Option selected: "))
if choice == 0:
noexit = False
elif choice == 1:
add_point(3,5,myPoints)
elif choice == 2:
myPoints.print_contents()
elif choice == 3:
ID = int(input("Please insert ID of point: "))
delete_point(myPoints.return_index_from_ID(ID),myPoints)

How to iterate for loop with values in different methods?

I made this program. What I want to do now, is to make a new method in the class Star_cluster that will count and return all planets in the star cluster that are in danger. In this case, a planet in danger is a planet with a star that has a short lifespan. A star has a short lifespan when it's total mass is more than 9.5 solar masses.
class Planet:
def __init__ (self, a_str1, a_str2, a_float):
self.name = a_str1
self.type = a_str2
self.orbital_period = a_float
class Star:
def __init__ (self, a_float, a_planet_list):
self.total_mass = a_float # in solar masses
self.orbiting_planets = a_planet_list # list of Planet-objects
class Star_cluster:
def __init__ (self):
self.star_list = [] # list of Star-objects
def add(self, Star):
self.star_list.append(Star)
My problem is that I don't get how I should combine the values in the different methods to make one for loop.
For example, I tried to make something like this:
class Star_cluster:
def planets_in_danger (self):
for i in self.orbiting_planets:
if i.total_mass > 9.5:
k = self.orbiting_planets.count(i)
return k
But I can't get this working. I want to understand how I should approach this problem, because I know what to do, but not entirely sure about how to do it the best way.
Especially whether to use self and the fact that there are multiple methods involved and just one for loop, confuses me. Could someone point me in the right direction?
Loop over all the stars in the given cluster. If a star's total mass exceeds 9.5, count the amount of planets that belong to that star to the amount of endangered planets.
def planets_in_danger(self):
in_danger = 0
for star in self.star_list:
if star.total_mass > 9.5:
in_danger += len(star.orbiting_planets)
return in_danger
Or shorter:
def planets_in_danger(self):
return sum(len(star.orbiting_planets) for star in self.star_list if star.total_mass > 9.5)
edit: returning the count of endangered planets and the planets:
def planets_in_danger(self):
in_danger = []
for star in self.star_list:
if star.total_mass > 9.5:
in_danger.extend(star.orbiting_planets)
return (len(in_danger), in_danger)
Call the function planets_in_danger in Star_Cluster
class Planet:
def __init__ (self, a_str1, a_str2, a_float):
self.name = a_str1
self.type = a_str2
self.orbital_period = a_float
class Star:
def __init__ (self, a_float, a_planet_list):
self.total_mass = a_float # in solar masses
self.orbiting_planets = a_planet_list # list of Planet-objects
class Star_cluster:
def __init__ (self):
self.star_list = [] # list of Star-objects
def add(self, Star):
self.star_list.append(Star)
def planets_in_danger(self, stars_list):
result = []
solar_mass = 1.989 * (10**30)
for i in stars_list:
if i.total_mass > 9.5 * solar_mass:
result.append(i)
return result

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

Classes, objects and lists in python

so I'm trying to create a program but I still have difficulties with classes. The program (which isn't finished of course) will print a random number of Villages. Each village(second Class) will have a random number of Clans(the first Class). Anyway my problem is the Village class. How do I make sure to add the areas and family size into the Village class? How do I insert the counter from the Clan class to the Village class? As you can see when I've randomized a number of Clans the areas and family sizes should add up into the Village class. What should I do? What is wrong with my Village class?
class Clan:
counter = 0
def __init__(self):
r = random.randrange(20, 101)
self.area = r
s = random.randrange(1, 6)
self.familySize = s
Clan.counter += 1
self.counter = Clan.counter
def getArea(self):
return self.area
def getFamilySize(self):
return self.familySize
class Village:
counter = 0
def __init__(self):
self.clan_list = []
for i in range(random.randrange(3, 7)):
self.clan_list += [Clan()]
def getclan_list(self):
return self.clan_list
def getArea(self):
return self.area
def getPopulation(self):
pass
So, you want the village class to calculate how many families are in the village?
families = 0
for clan in self.clan_list
families += clan.getFamilySize()
Since the values of area and population are dependent on the clans in clan_list you should compute these values each time they are needed. The alternative is much more complicated -- having to control how clans are added and removed from the village and how the area and family size of a clan can be changed and having those changes reflected in the village.
Below is an example of how you might compute both village area and population. The first using a getter method, and the second using a more python-esque property.
import random
class Clan:
counter = 0
def __init__(self):
r = random.randrange(20, 101)
self.area = r
s = random.randrange(1, 6)
self.familySize = s
Clan.counter += 1
self.counter = Clan.counter
# removed getters
# Unless your getter or setter is doing something special,
# just access the attribute directly.
class Village:
def __init__(self):
self.clan_list = []
for i in range(random.randrange(3, 7)):
self.clan_list.append(Clan())
# for a village, area is a computed value, so use a getter
def getArea(self):
total_area = 0
for clan in self.clan_list:
total_area += clan.area
return total_area
# the prefered alternative to getters (and setters) are properties
# note that the function is named as if it was an attribute rather than function
#property
def population(self):
# use sum and generator rather than a for loop
return sum(clan.familySize for clan in self.clan_list)
# How to use a village instance
v = Village()
# get area
print("area:", v.getArea())
# get population
print("population:", v.population)
# note how population is accessed as if it was an attribute rather than called
# like a function

Python - Compare two lists and find matching values and their positions in the list

I am trying to make a turn based RPG and I am currently working on the turn system.
To keep it simple for now I am trying to order each character/enemy by their speed and then highest speed goes first. Below is the start of my code for the turn system.
An example of what I want to do is read Order[0] (which will be the fasted character/enemy) and find out which character/enemy that relates to. Speed[0] to Speed[3] gives the speed of my 4 characters and enemySpeed[0] to enemySpeed[4] gives the speed of the 5 enemies.
def Turn():
Turn = [int(Speed[0]), int(Speed[1]), int(Speed[2]), int(Speed[3]), int(enemySpeed[0]), int(enemySpeed[1]),int(enemySpeed[2]), int(enemySpeed[3]), int(enemySpeed[4])]
Order = sorted(Turn, key = int, reverse = True)
Edit: Here is some information regarding player stats.
In main():
name = ['Ben','Ellis','Curt','Jen']
HP = [100,100,100,100]
exp = [0,0,0,0]
lvl = [1,1,1,1]
player1 = [name[0],HP[0],exp[0],lvl[0]]
player2 = [name[1],HP[1],exp[1],lvl[1]]
player3 = [name[2],HP[2],exp[2],lvl[2]]
player4 = [name[3],HP[3],exp[3],lvl[3]]
PLAYERS = [player1, player2, player3, player4]
REGION = 'start'
POS = '[x, y]'
ITEMS = None
SIGEVENTS = False
gameData = [PLAYERS, REGION, POS, ITEMS, SIGEVENTS]
Out of main():
def playerStats():
global Attack, Defense, Speed, MaxHP
Attack = [0,0,0,0]
Defense = [0,0,0,0]
Speed = [0,0,0,0]
MaxHP = [0,0,0,0]
for i in range(0,4):
Attack[i] = lvl[i] * 1
Defense[i] = lvl[i] * 2
Speed[i] = lvl[i] * 3
MaxHP[i] = lvl[i] * 4
return Attack, Defense, Speed, MaxHP
Instead of looking at just the speeds, look at your players and enemies, and devise a key to determine what speed goes with what player.
You didn't share any details on how you define players and speeds; I'll use a number here for now:
players_and_enemies = range(8)
fastest = max(players_and_enemies, key=lambda p: int(Speed[i] if i < 4 else enemySpeed[i - 4]))
It may well be that you can simplify this based on your data structures; if you have objects per player and enemy that have a speed attribute, for example, you can access that attribute in the key function instead.
max() returns the highest value by key; no need to sort all speeds if all you need is the fastest driver.
Martijn Pieters already pointed out the most important issues. Try to use objects. Try to remodel the objects of your game and don't manage their attributes seperately.
I will elaborate a bit on this and maybe I can give you so some ideas.
A Character, be it a NPC or a PC, is one object of a class that could look something like this:
class Character:
def __init__ (self, name, xp = 0, level = 1, hp = 4, speed = 3, atk = 1, def_ = 2):
self.name = name
self.xp = xp
self.level = level
self.hp = self.curHp = hp
self.speed = speed
self.atk = atk
self.def_ = def_
self.inventory = []
Now using this class you can instantiate your PCs and NPCs:
npcs = [Character (name) for name in ['Baldur', 'Lord Never', 'Ashyra'] ]
Adding methods to your class lets you interact with it, for example:
class Character:
[....]
def takeDamage (self, dmg):
self.curHp -= min (0, dmg - self.def_)
def gainXP (self, xp):
self.xp += xp
#check for level up
def takeItem (self, item):
self.inventory.append (item)
def useItem (self, item):
item.activate ()
self.inventory.remove (item)
Or in order to get all your characters ordered by their speed, you can use:
charactersBySpeed = sorted (characters, key = -character.speed)
And so further and so on. The idea is really to use object oriented programming for modelling the reality (even the made-up reality of your game) in your code.

Categories

Resources