繁体   English   中英

使用.format(** self .__ dict__)在__str__中打印单个列表对象

[英]Printing individual list objects within __str__ using .format(**self.__dict__)

我正在为游戏角色对象打印一个统计块。 在上一个问题中,向我展示了一种在__str__函数中使用显示对象数据的方法,如下__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变量有关。 这些项目在“角色”对象中定义为单个项目列表: weapon=[] ,依此类推。 使用上述方法将返回列表对象,而不是列表对象所包含的没有[]的对象。 我评价者看到一个空白的" "字符串或列表中的包含的对象(如果存在),而不是[]

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

我尝试了许多实验,包括在定义current_weapon = weapon[0]之后,用{current_weapon}替换{weapon}引用,如果列表对象为空,则该方法将不起作用。 那只是IndexError: list index out of range错误IndexError: list index out of range 我可以在对象实例化时生成项目,但由于self.item会是一个空列表容器,因此无法正常工作。

我可以传播带有" "对象的列表,但随后必须用替换项目将它们弄乱,并保持跟踪状态,这看起来非常微不足道,而且可能很麻烦。

我似乎似乎无法用一种优雅的方式来按照目前的设计在上述__str__返回中打印列表对象。 我仍在学习Python,并且想相信我可以在此return字符串后面添加一个简单的附加内容来完成此操作。

另一种选择是使用字符串格式化的功能来检查所传入内容的属性,以及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())

您可以只创建字典的本地副本,并在将其传递给格式之前修改所需的值:

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所做的self.status 现在,您只是在修改临时副本。

即使不是那么简单,您也可以通过简单的方法来完成。 您可以修改字符串格式以容纳整个对象并利用属性的功能,这具有不创建字典副本的优点,这对于大型对象而言可能很昂贵。

我将给您一个示例,该示例应与您的需求相近:

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

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

如果您不喜欢0.c_str表示法,则可以以不同的方式对其进行转义,例如,使其与通常的表示法保持接近:

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

要么

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

暂无
暂无

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

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