This question already has answers here:
How do I create variable variables?
(17 answers)
How can you dynamically create variables? [duplicate]
(8 answers)
Closed 7 years ago.
I'm currently making a game for CompSci class, and I want to shorten our random monster fights. Is there a way to make it so when I call a def I can change the name depending on a random variable? This is the snippet I'm talking about
Loop = True
MonsterType = random.randint(1,20)
Monster*()
battle()
I have
def Monster1
def Monster2
def Monster3
.
.
.
def Monster20
I want the * in the first snippet to be the variable MonsterType, is there a way to have it do that? I.e. When it runs, if MonsterType = 15, then it'll be Monster13() that's called.
Yes there is a way, Create a dictionary and map each function to an integer:
import random
def monster1():
print "Hello monster1"
def monster2():
print "Hello monster2"
def monster3():
print "Hello monster3"
def monster4():
print "Hello monster4"
d = {1:monster1, 2:monster2, 3:monster3, 4:monster4}
#When you need to call:
monsterType = random.randint(1, 4)
d[monsterType]()
After reading what you're trying to accomplish, I believe that using OOP is going to be better for your situation:
# A class for a bunch of monsters
class Mob(object):
def __init__(self, num_monsters):
self._num_monsters = num_monsters
self._monsters = []
for i in range(self._num_monsters):
# randomly create a type of monster based on the number of monsters
self._monsters.append(Monster(random.randint(0, self._num_monsters)))
# Each monster has a type that is attacks with
class Monster(object):
def __init__(self, monster_type):
self._type = monster_type
def attack(self):
print(self._type)
test = Mob(20)
sounds like you you use a bit of OOP. I would recommend:
class Monster(object):
def __init__(self, name):
self.name = name
def do_work(self):
print self.name
then create a manager that can generate n number of monster objects, and provide a static method that can manage what object to call:
class MonsterManager(object):
monsters = []
def call_monster(self, index):
monsters[i].do_work()
with this, you can have a better useage, like so:
manager = MonsterManager();
manager.monsters.append(Monster('Monster1')
manager.monsters.append(Monster('Monster2')
# etc
# then call a single monster
manager.call_monster(i)
Related
This question already has answers here:
How to avoid having class data shared among instances?
(7 answers)
Closed 7 months ago.
I have code that creates a "Box" object, with a unique number assigned to each Box, then a unique number assigned as the contents for each Box. multiple boxes then make up a "Room" object.
Here's the thing, when I run multiple iterations to create a new Room object, each room iteration creates the exact same room object. By running this code, you see that box 0 prints the same for every iteration. Why is that, and how can I get a unique combination of box contents on each iteration?
import random
class Box:
def __init__(self, box_number, box_content):
self.number = box_number
self.content = box_content
def __str__(self):
return f"Box: {self.number} | Content: {self.content}"
class Room:
boxes = []
def __init__(self, num_of_boxes):
box_contents = [*range(num_of_boxes)]
random.shuffle(box_contents)
for i in range(num_of_boxes):
self.boxes.append(Box(i + 1, box_contents[i] + 1))
def run_cycle():
room = Room(5)
print(room.boxes[0])
for _ in range(5):
run_cycle()
class Room:
def __init__(self, num_of_boxes):
self.boxes = []
...
def 'boxes' inside init belong to an instance.
Your code's all Room instance has same box attrib which belong to class.
This question already has answers here:
One int for every python object [duplicate]
(3 answers)
Closed 4 years ago.
Sorry, if the title seemed a little imprecise.
I'm wondering if there is way of making sure that every instance of an object can have a unique serial number?
class Airplane:
def __init__(self, name, passenger_hold):
self.name = name
self.passenger_hold = passenger_hold
airplane1 = Airplane("Airbus A320", 100)
airplane2 = Airplane("Boeing 747", 250)
How can I make sure that the first airplane has the serial number 0, the second one 1 and so on?
Use a global counter, internal to your class that would give you a new value each time the constructor is called.
class Airplane:
counter = 0
def __init__(self, name, passenger_hold):
self.name = name
self.passenger_hold = passenger_hold
self.serial = Airplane.counter
Airplane.counter += 1
This question already has answers here:
Passing variables between methods in Python?
(5 answers)
Closed 6 months ago.
I am taking an input temp from user in method parameter and I want to compare this temp with another variable oven_temp in the make_item method. But I get a NameError, saying that name temp is not defined.
I read some posts here and I understood that I need to return the value from the method - so I did that; but now what? Specifically, I tried:
class maker:
def parameter(self):
temp = int(input('At what temperature do you want to make \n'))
return temp
def make_item(self):
def oven (self):
oven_temp = 0
while (oven_temp is not temp):
oven_temp += 1
print ("waiting for right oven temp")
oven(self)
person = maker()
person.parameter()
person.make_item()
but I still get the NameError. How do I fix it?
The following should work to solve your problem. Basically, you want to store the variables you want to pass between methods as members of the class. You do this by assigning an attribute of the self parameter to the functions.
class maker:
def parameter(self):
self.temp = int (input ('At what temperature do you want to make \n'))
def make_item (self):
def oven ():
oven_temp = 0
while (oven_temp is not self.temp):
oven_temp += 1
print ("waiting for right oven temp")
oven()
person = maker ()
person.parameter()
person.make_item()
Keep it in yourself!
class MyMaker:
def ask_temperature(self):
self.temp = int(input('Temperature? \n'))
def print_temperature(self):
print("temp", self.temp)
Try it:
> maker = MyMaker()
> maker.ask_temperature()
Temperature?
4
> maker.print_temperature()
temp 4
For context, I'm working on an inventory system in an RPG, and I'm prototyping it with python code.
What I don't understand is how to make separate variables for each instance of an item without declaring them manually. For a short example:
class Player(object):
def __init__(self):
self.Items = {}
class Item(object):
def __init__(self):
self.Equipped = 0
class Leather_Pants(Item):
def __init__(self):
#What do i place here?
def Pick_Up(self, owner):
owner.Items[self.???] = self #What do i then put at "???"
def Equip(self):
self.Equipped = 1
PC = Player()
#Below this line is what i want to be able to do
Leather_Pants(NPC) #<-Create a unique instance in an NPC's inventory
Leather_Pants(Treasure_Chest5) #Spawn a unique instance of pants in a treasure chest
Leather_Pants1.Pick_Up(PC) #Place a specific instance of pants into player's inventory
PC.Items[Leather_Pants1].Equip() #Make the PC equip his new leather pants.
If I did something silly in the above code, please point it out.
What I want to do if the code doesn't make it clear is that I want to be able to dynamically create variables for all items as I spawn them, so no two items will share the same variable name which will serve as an identifier for me.
I don't mind if I have to use another class or function for it like "Create_Item(Leather_Pants(), Treasure_Chest3)"
What's the best way to go about this, or if you think I'm doing it all wrong, which way would be more right?
As a general rule, you don't want to create dynamic variables, and you want to keep data out of your variable names.
Instead of trying to create variables named pants0, pants1, etc., why not just create, say, a single list of all leather pants? Then you just do pants[0], pants[1], etc. And none of the other parts of your code have to know anything about how the pants are being stored. So all of your problems vanish.
And meanwhile, you probably don't want creating a Leather_Pants to automatically add itself to the global environment. Just assign it normally.
So:
pants = []
pants.append(Leather_Pants(NPC))
pants.append(Leather_Pants(chests[5]))
pants[1].pickup(PC)
The pants don't have to know that they're #1. Whenever you call a method on them, they've got a self argument that they can use. And the player's items don't need to map some arbitrary name to each item; just store the items directly in a list or set. Like this:
class Player(object):
def __init__(self):
self.Items = set()
class Item(object):
def __init__(self):
self.Equipped = 0
class Leather_Pants(Item):
def __init__(self):
pass # there is nothing to do here
def Pick_Up(self, owner):
self.owner.Items.add(self)
def Equip(self):
self.Equipped = 1
Abernat has tackled a few issues, but I thought I weigh in with a few more.
You appear to be using OOP, but are mixing a few issues with your objects. For example, my pants don't care if they are worn or not, I care though for a whole host of reasons. In python terms the Pants class shouldn't track whether it is equipped (only that it is equippable), the Player class should:
class CarryableItem:
isEquipable = False
class Pants(CarryableItem):
isEquipable = True
class Player:
def __init__(self):
self.pants = None # Its chilly in here
self.shirt = None # Better take a jumper
self.inventory = [] # Find some loot
def equip(self,item):
if is.isEquipable:
pass # Find the right slot and equip it,
# put the previously equipped item in inventory, etc...
Also, its very rare that an item will need to know who its owner is, or that its been grabbed, so verbs like that again should go onto the Player:
class Player:
maxCarry = 10
def take(Item):
if len(inventory) < maxCarry:
inventory.append(item)
Lastly, although we've tried to move most verbs on to actors which actually do things, sometimes this isn't always the case. For example, when instantiating a chest:
import random
class StorageItem:
pass
class Chest(StorageItem):
__init__(self):
self.storage = random.randint(5)
self.loot = self.spawnLoot()
def spawnLoot(self):
for i in range(self.storge):
# Lets make some loot
item = MakeAnItem # Scaled according to type level of dungeon, etc.
loot.append(item)
def remove(item):
self.loot[self.loot.index(item)]=None
Now the question about what to do when a Player wants to plunder a chest?
class Player:
def plunder(storage):
for item in storage.loot:
# do some Ui to ask if player wants it.
if item is not None and self.wantsItem(item) or \
(self.name="Jane" and self.wantsItem(item) and self.doesntWantToPay):
self.take(item)
storage.remove(item)
edit: Answering the comment:
If you are curious about calculating armor class, or the like, that again is a factor of the user, not the item. For example:
class Player:
#property
def clothing(self):
return [self.pants,self.top]
#property
def armorClass(self):
ac = self.defence
for item in self.clothing:
def = item.armorClass
if self.race="orc":
if item.material in ["leather","dragonhide"]:
def *= 1.5 # Orcs get a bonus for wearing gruesome dead things
elif item.material in ["wool","silk"]:
def *= 0.5 # Orcs hate the fineries of humans
ac += def
return ac
pants = Pants(material="leather")
grum = Player(race="orc")
grum.equip(pants)
print grum.armorClass
>>> 17 # For example?
I have a homework assignment that's really baking my noodle. It involves an elevator simulation that takes user inputs for the number of floors and the number of people using the elevator. the people's starting floor and destination floors are random numbers within the floors.
I realize that my code is very sparse and that there's quite a few gaps, but I really don't know where to go from here.
I need help within the building class, such as how to make the run() and output() sections work. any other tips would be greatly appreciated and helpful. Note that i am not looking for someone to do the code for me, but to kind of hold my hand and tell me which way to go. Classes seem to be completely mystifying to me.
import random
floors=raw_input('Please enter the number of floors for the simulation:')
while floors.isalpha() or floors.isspace() or int(floors) <=0:
floors=raw_input('Please re enter a digit for number of floors:')
customers=raw_input('Please enter the number of customers in the building:')
while customers.isalpha() or customers.isspace() or int(customers) <0:
customers=raw_input('Please re enter a digit for number of customers:')
count = 1
class building:
def num_of_floors():
num_of_floors = floors
def customer_list():
customer_list = customers
def run(self):
def output(self):
print elevator.cur_floor
class elevator:
def num_of_floors():
building.num_of_floors
def register_list():
register_list = []
def cur_floor(building):
cur_floor = 1
def direction(self):
if elevator.cur_floor == 1:
direction = up
if elevator.cur_floor == floors:
direction = down
def move(self):
if elevator.direction == up:
cur_floor +=1
if elevator.direction == down:
cur_floor -=1
def register_customer(self, customer):
register_list.append(customer.ID)
def cancel_customer (self, customer):
register_list.remove(customer.ID)
class customer:
def cur_floor(customer):
cur_floor = random.randint(0,int(floors))
def dst_floor(customer):
dst_floor = random.randint(0,int(floors))
while dst_floor == cur_floor:
dst_floor = random.randint(0,int(floors))
def ID():
cust_id = count
count+=1
def cust_dict(cust_id,dst_floor):
cust_dict = {cust_id:dst_floor}
def in_elevator():
in_elevator = 0
if customer.ID in register_list:
in_elevator = 1
def finished():
if customer.ID not in register_list:
pass
You need to understand the self
parameter to all methods.
You need to understand __init__,
the constructor.
You need to understand self.varible
for your member variables.
You need to understand how to setup a
main function.
You need to understand how to
return a value from a function or
method.
You need to understand how to assign to global variables from within a function or method.
Maybe your building class should start like this.
class building:
def __init__(self, floors, customers):
self.num_of_floors = floors
self.customer_list = customers
self.elevator = elevator()
You should definately spend some time on Python Tutorial or Dive into Python.
The first parameter of every method is a reference to the object and is usually called self. You need it to reference instancemembers of an object.
Second, referencing global variables from inside a class is considered a bad idea. You can better pass them to a class via the constructor or parameters.