[英]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)
pc是Player类的对象,该类具有已在代码中定义的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.