0

我正在为游戏角色对象打印一个统计块。在上一个问题中,我展示了一种在__str__函数中使用显示对象数据的方法,如下所示:

def __str__(self):
    if self.poisoned is True:
        status = "[POISONED]"
    else:
        status = ""
    self.status = status
    return ('NAME: {name} {status}\n' \
            'XP:   {xp}\n' \
            'HP:   {hit_points}\n' \
            'SP:   {spell_points}\n' \
            'STR:  {strength}\n' \
            'DEX:  {dexterity}\n' \
            'WEAPON: {weapon}\n' \
            'SPELL:  {spell}\n' \
            'ITEM:   {item}\n' \
            'AURA:   {aura}\n' \
            ).format(**self.__dict__)

我要解决的问题与 WEAPON、SPELL、ITEM 和 AURA 变量有关。这些项目在 Character 对象中定义为单个项目列表:weapon=[]等等。使用上述方法返回列表对象,而不是它包含的不带[]. " "如果存在且不存在,我会看到一个空白字符串或列表包含的对象[]

NAME: Bones 
XP:   0
HP:   100
SP:   100
STR:  14
DEX:  19
WEAPON:   []
SPELL:    []
ITEM:     []
AURA:     []

我已经尝试了许多实验,包括在定义列表对象为空时哪个不起作用之后替换{weapon}引用。那只是错误。我可以在对象实例化时生成项目,但这有时会不起作用,因为有时会是一个空列表容器。{current_weapon}current_weapon = weapon[0]IndexError: list index out of rangeself.item

我可以使用对象传播列表," "但随后必须将它们与替换项目一起处理并跟踪这似乎非常不优雅且可能很麻烦。

我似乎无法用一种优雅的方式来__str__按照当前设计的方式在上述返回中打印列表对象。我仍在学习 Python,并希望相信有一个简单的添加可以附加到这个return字符串中来做到这一点。

4

3 回答 3

2

self另一种选择是使用字符串格式化的力量来检查它传入的属性,以及方法中的局部变量这一事实:

def __str__(self):
    status = '[POISONED]' if self.poisoned else ''
    weapon = self.weapon[0] if self.weapon else ''
    spell = self.spell[0] if self.spell else ''
    item = self.item[0] if self.item else ''
    aura = self.aura[0] if self.aura else ''
    return ('NAME: {self.name} {status}\n'
            'XP:   {self.xp}\n'
            'HP:   {self.hit_points}\n'
            'SP:   {self.spell_points}\n'
            'STR:  {self.strength}\n'
            'DEX:  {self.dexterity}\n'
            'WEAPON: {weapon}\n'
            'SPELL:  {spell}\n'
            'ITEM:   {item}\n'
            'AURA:   {aura}\n'
            ).format(**locals())
于 2012-11-28T02:30:01.330 回答
1

您可以只创建您的字典的本地副本,并修改您想要的值,然后将其传递给格式:

def __str__(self):
    local_data = self.__dict__.copy()

    local_data['status'] = "[POISONED]" if self.poisoned else ""

    local_data['weapon'] = " " if not self.weapon else ','.join(self.weapon)

    return ('NAME: {name} {status}\n' \
            'XP:   {xp}\n' \
            'HP:   {hit_points}\n' \
            'SP:   {spell_points}\n' \
            'STR:  {strength}\n' \
            'DEX:  {dexterity}\n' \
            'WEAPON: {weapon}\n' \
            'SPELL:  {spell}\n' \
            'ITEM:   {item}\n' \
            'AURA:   {aura}\n' \
            ).format(**local_data)

这样做可能比修改简单的格式属性更好,就像你对self.status. 现在您只是在修改临时副本。

于 2012-11-28T01:46:04.820 回答
1

即使不是那么微不足道,您也可以通过简单的方式做到这一点。您可以修改字符串格式以获取整个对象并利用属性的力量。这具有不创建字典副本的优点,这对于大对象来说可能很昂贵。

我会给你一个应该接近你需要的例子:

class A(object):
    def __init__(self):
        # one full list and one empty one
        self.c = [1,2,3]
        self.d = []

    #these two preperties create a string versione when requeste
    c_str = property(lambda self: ", ".join(str(i) for i in self.c))
    d_str = property(lambda self: ", ".join(str(i) for i in self.d))

    def __str__(self):
        #you have to use the dotted version because properties are not visibles 
        # from the dict attribute
        string = "c = {0.c_str} \nd = {0.d_str}"
        return string.format(self)
a = A()
print str(a)
# c = 1, 2, 3 
# d = 

如果您正在编写某种游戏属性,则可能是一个巨大的救星,因为您可以使用它们来获取复杂的值作为属性而不是函数,从而创建更清晰的代码。它们允许您甚至检查值的插入,例如值是正数。

编辑:

为什么我使用0.c_str而不是c_str?这是因为属性是特殊对象,只有当您使用点符号 ( ) 访问它们时才会调用它们self.c_str。它们不存在于对象 __dict__ 中,因此您无法使用它。如果您尝试打印 __dict__ ,您将只看到值cd

这就是为什么我将整个对象传递给格式函数并访问其属性而不是传递对象字典的原因。

如果您不喜欢该0.c_str符号,您可以以不同的方式对其进行转义,例如使其接近通常的符号:

"{self.c_str}".format(self=self)

或者

"{foo.c_str}".format(foo=self)
于 2012-11-28T01:56:45.880 回答