简体   繁体   中英

How do you take an input and call an instance of a class based on the input?

I am currently developing a short text-based adventure so I can learn how to use Classes within Python. As part of this, I am trying to create a combat system where the player could choose an NPC to attack.

The aim is that the player can enter the name of the NPC and the weapon they want to use. A method in the target's class will then be called, to lose health based on the damage of the weapon.

My current code is below:

class npc:
    def __init__(self, name, alliance):
        self.name = name
        self.alliance = alliance
    def loseHealth(self, health, dmg):
        self.dmg = dmg
        self.health = self.health - dmg
    def usePotion(self, health, pType):
        if pType == "great":
            self.health = min(self.health + 50,self.maxHealth)
        elif pType == "normal":
            self.health = min(self.health + 25,self.maxHealth)
        else:
            pass
    def attack(self, target, weaponDmg):
        if target in npcList:
            target.loseHealth(self.health, weaponDmg)

class human(npc):
    maxHealth = 100
    health = 100
    def __init__(self, name, alliance):
        super().__init__(name, alliance)

class orc(npc):
    maxHealth = 200
    health = 200
    def __init(self, name, alliance):
        super().__init__(name, alliance)

weaponDmg = {'sword':10,'axe':20}
alice = human("alice","good")
bob = orc("bob","evil")
npcList = [alice, bob]
target = input("Enter Target:")
weapon = input("Enter weapon:")
for x in range(3):
    alice.attack(target,weaponDmg[weapon]) #using alice temporarily until I have a person class sorted
    print(target.health)

You can call a method on an instance by using getattr , here is an example:

>>> class Test:
...     def my_method(self, arg1, arg2):
...         print(arg1, arg2)
... 
>>> t = Test()
>>> getattr(t, 'my_method')('foo', 'bar')
foo bar

The simple and pythonic answer is to use a dict of NPCs keyed by name, the same way you're already doing it with weapons:

npcs = {‘alice’: alice, ‘bob’: bob}
target = input("Enter Target:")
weapon = input("Enter weapon:")
for x in range(3):
    alice.attack(npcs[target], weaponDmg[weapon])
    print(target.health)

And if you want to look up the attacking NPC by user-supplied name as well as the attackee, you can do the same thing there:

npcs[attacker].attack(npcs[target], weaponDmg[weapon])

If you really want to do this inside the attack method you can keep passing in target as a name (string) and do this:

   if target in npcs:
        npcs[target].loseHealth(self.health, weaponDmg)

... but that probably isn't a very good design. It means you're sharing a global variable, and your NPC objects all “know” about that global dict and all the NPCs in it, which doesn't seem like part of their responsibility.


You can make this a little less repetitive by creating the dict with a comprehension:

npcs = {npc.name: npc for npc in (alice, bob)}

... or by just creating them directly in the dict instead of in variables that you're probably never going to otherwise use:

npcs = {}
npcs[‘alice’] = human("alice","good")
npcs[‘bob’] = orc("bob","evil")

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM