简体   繁体   English

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

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

I'm printing a stat block for a game character object. 我正在为游戏角色对象打印一个统计块。 In a previous question I was demonstrated a way to display the object data using in the __str__ function like so: 在上一个问题中,向我展示了一种在__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__)

The problem I want to solve has to do with the WEAPON, SPELL, ITEM and AURA variables. 我要解决的问题与WEAPON,SPELL,ITEM和AURA变量有关。 These items are defined in the Character object as single item lists: weapon=[] and so on. 这些项目在“角色”对象中定义为单个项目列表: weapon=[] ,依此类推。 Using the above method returns the list object instead of the object it contains without the [] . 使用上述方法将返回列表对象,而不是列表对象所包含的没有[]的对象。 I'd rater see a blank " " string or the list's contained object if one exists and not [] . 我评价者看到一个空白的" "字符串或列表中的包含的对象(如果存在),而不是[]

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

I've tried a number of experiments including replacing the {weapon} reference with {current_weapon} after defining current_weapon = weapon[0] which won't work if the list object is empty. 我尝试了许多实验,包括在定义current_weapon = weapon[0]之后,用{current_weapon}替换{weapon}引用,如果列表对象为空,则该方法将不起作用。 That just errors with IndexError: list index out of range . 那只是IndexError: list index out of range错误IndexError: list index out of range I could generate the items at object instantiation, but that won't work as self.item will at times be an empty list container. 我可以在对象实例化时生成项目,但由于self.item会是一个空列表容器,因此无法正常工作。

I could propagate the lists with " " objects but would then have to juggle them out with replacement items and keep track of this which seems very inelegant and potentially cumbersome. 我可以传播带有" "对象的列表,但随后必须用替换项目将它们弄乱,并保持跟踪状态,这看起来非常微不足道,而且可能很麻烦。

I just can't seem to wrap my head around an elegant way to print the list object in the above __str__ return as currently designed. 我似乎似乎无法用一种优雅的方式来按照目前的设计在上述__str__返回中打印列表对象。 I'm still learning Python and want to believe there is a simple addition I could append to this return string to do this. 我仍在学习Python,并且想相信我可以在此return字符串后面添加一个简单的附加内容来完成此操作。

Another option is to use the power of string formatting to check attributes of what it's passed in, and the fact that self is a local variable within the method: 另一种选择是使用字符串格式化的功能来检查所传入内容的属性,以及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())

You could just create a local copy of your dict, and modify the values you want, before passing that on to the format: 您可以只创建字典的本地副本,并在将其传递给格式之前修改所需的值:

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)

It is probably better to do that, than to modify your attributes simple for the formatting, like you were doing with your self.status . 这样做可能比修改格式简单的属性要好,就像您对self.status所做的self.status Now you are just modifying temp copies. 现在,您只是在修改临时副本。

You can do it in a simple way, even if not so trivial. 即使不是那么简单,您也可以通过简单的方法来完成。 You can modify the string format to take the whole object and harness the power of the properties.This has the advantage of not creating a copy of your dictionary, that can be expensive for big object. 您可以修改字符串格式以容纳整个对象并利用属性的功能,这具有不创建字典副本的优点,这对于大型对象而言可能很昂贵。

I'll give you an example that should be close to what you need: 我将给您一个示例,该示例应与您的需求相近:

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 = 

If you are programming some kind of game properties can be a huge lifesavers, as you can use them to obtain complicated values as attribute instead of functions, creating a lot more cleaner code. 如果您正在编程,那么某些游戏属性可能是巨大的救星,因为您可以使用它们来获取复杂的值作为属性而不是函数,从而创建了更简洁的代码。 They allow you to implement even check for the insertion of value, for examples that a value is positive. 它们使您甚至可以检查是否插入了值,例如,值是正数。

EDIT: 编辑:

Why I am using the 0.c_str instead of c_str ? 为什么我使用0.c_str而不是c_str it is because the properties are special objects that will be called only if you access them with the dot notation ( self.c_str ). 这是因为属性是特殊对象,仅当您使用点符号( self.c_str )访问它们时才会调用它们。 They do not exist in the objects __dict__ so you can't use it. 它们不存在于对象__dict__中,因此您无法使用它。 If you try to print the __dict__ you will see only the values c and d . 如果尝试打印__dict__,则只会看到值cd

That's why I passed to the format function the whole object and accessed its attributes instead of passing it the object dictionary. 这就是为什么我将整个对象传递给format函数并访问其属性,而不是将其传递给对象字典。

If you don't like the 0.c_str notation you can escape it differently, for example keeping it close to the usual notation: 如果您不喜欢0.c_str表示法,则可以以不同的方式对其进行转义,例如,使其与通常的表示法保持接近:

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

or 要么

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

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

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