繁体   English   中英

如何将cmd.Cmd命令的参数类型从str更改为对象

[英]How to change argument type from str to an object for a cmd.Cmd command

我想创建一个cmd.Cmd命令,该命令接受一个使用消耗品的参数(这是基于文本的冒险)

import cmd
class Adventure(cmd.Cmd):
    prompt = ">"

# Other commands cut out because they are not part of the problem   

    def do_use(self, arg):
        arg.use(pc)

其中arg将是Consumable类的对象,并且之前已经在代码中定义了self.use(target)函数(在示例中为potion对象)

class Consumable:
    def __init__(self, hpgain):
        self.hpgain = hpgain

    def use(self, target):
        inventory.remove(self)
        target.addhp(self.hpgain)

potion = Consumable(5)
inventory = []
inventory.append(potion)

pcPlayer类的对象,该类具有已在代码中定义的self.addhp(amount)函数

class Player:
    def __init__(self, hp):
        self.hp = hp
        self.maxhp = hp

    def addhp(self, amount):
        self.hp += amount
        if self.hp > self.maxhp:
            self.hp = self.maxhp

pc = Player(20)

potion.use(pc)pc.addhp(amount)函数均在标准Python Shell中运行

当我尝试使用在自定义外壳程序中键入使用药水药水对象时,会发生以下错误:

Traceback (most recent call last):
  File "C:\Users\[Redacted]\Desktop\adventure.py", line 225, in <module>
    Adventure().cmdloop()
  File "C:\Python37\lib\cmd.py", line 138, in cmdloop
    stop = self.onecmd(line)
  File "C:\Python37\lib\cmd.py", line 217, in onecmd
    return func(arg)
  File "C:\Users\[Redacted]\Desktop\adventure.py", line 199, in do_use
    arg.use(pc)
AttributeError: 'str' object has no attribute 'use'

因此,它将函数的参数视为字符串而不是对象。 我该如何改变?

Cmd模块将每个arg解析为命令行参数,在这种情况下,它是一个字符串。 在Python中,有几种方法可以按名称查找当前加载到内存中的objects globals就是其中之一。 如果您要定位的对象恰好在另一个模块中声明了ie( x=5 ),那么我们可以改用getattr(module_name, var_name)

class Adventure(cmd.Cmd):
    prompt = ">"

# Other commands cut out because they are not part of the problem   

    def do_use(self, arg):
        globals()[arg].use(pc) #if potion is declared in the current module
        #getattr(module_where_it_is_declared, arg).use(pc) #if potion is declared in another module

让我知道这是否有效!

我将创建一个类似以下的Inventory类:

from cmd import Cmd
from collections import Counter


class Inventory(Counter):
    """
    We can extend the Inventory class later. For now it will work as a Counter
    so that we can keep track of the number of each item it has
    """


class Player:
    def __init__(self, hp):
        self.hp = hp
        self.maxhp = hp
        self.inventory = Inventory()

    def has(self, item_name):
        # Check that there is a positive amount of that item
        return item_name in self.inventory and self.inventory[item_name] > 0

    def use(self, item_name, item):
        # We are passing both the item_name and the item as we want to use it
        # We could also use the item itself as the key for the Inventory instead
        # of the item name, so that we do not need both (method has would also
        # need an update in that case)

        # Check if it is consumable to reduce the amount by one
        if isinstance(item, Consumable):
            self.inventory[item_name] -= 1

        # Use the item passing the player as it will have to access its addhp method
        item.use(self)

    def addhp(self, amount):
        self.hp += amount
        if self.hp > self.maxhp:
            self.hp = self.maxhp


class Consumable:  # You should probably add a base class Item later
    def use(self, player):
        pass  # This will be overwritten by other classes


class Potion(Consumable):
    """
    The Potion class allows to define different sizes of pots that will heal
    the player the specified amount.
    """
    def __init__(self, hp):
        """Define the amount of hp that a potion heals."""
        self.hp = hp

    def use(self, player):
        """Heal the player by the specified amount."""
        player.addhp(self.hp)


class Adventure(Cmd):
    prompt = ">"

    # This is just a map of item names to their current objects
    items = {
        "small potion": Potion(2),
        "potion": Potion(5),
        "big potion": Potion(10),
    }

    def __init__(self, *args, **kwargs):
        # Call parent class constructor IMPORTANT!
        super().__init__(*args, **kwargs)
        # Now we handle our own instance variables
        self.player = Player(20)

    def do_use(self, item_name):
        # Check before using
        if self.player.has(item_name):
            self.player.use(item_name, self.items[item_name])

do_use方法不是线程安全的,因此,无论何时添加不同的线程,请记住应该在某处添加使用锁。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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