【问题标题】:__str__ method iterating over class attributes__str__ 方法迭代类属性
【发布时间】:2019-05-17 19:56:36
【问题描述】:

我有一个属性由几个列表组成的类(今天是 8 个,但它肯定会增长,因为我的代码依赖于另一个项目的 prod 上使用的先前代码)

这个类有一个__str__ 函数来漂亮地打印列表的信息。今天,该函数显示有关每个列表的信息,但即调用它们,我不喜欢那样,因为每次我的类属性更改(添加/删除列表)时,我都必须更新此方法

我正在寻找一种方法来动态迭代我的类属性以显示信息

作为一个例子,让我们想象下面的类

class shopping_cart:
    def __init__(self):
        self.fruits = []
        self.vegetables = []
        self.meat = []
        self.bread = []

    def __str__(self):
        msg = ""
        msg += "shopping cart content\n"
        msg += "---------------------\n"
        msg += "---fruits-----------: " + len(self.fruits) +"\n
        msg += "---vegetables-------: " + len(self.vegetables) +"\n
        msg += "---meat-------------: " + len(self.meat) +"\n
        msg += "---bread------------: " + len(self.bread) +"\n
        return msg

如您所见,维护成本很高。我正在寻找更有活力的东西,看起来更像

class shopping_cart:
    def __init__(self):
        self.fruits = []
        self.vegetables = []
        self.meat = []
        self.bread = []

    def __str__(self):
        msg = ""
        msg += "shopping cart content\n"
        msg += "---------------------\n"
        for item in <list of my class attributes>:
            msg += "---" + item +"-----------: " + len(item) +"\n
        return msg

易于阅读且易于维护。

【问题讨论】:

  • 在你的例子中,我宁愿使用一个字典而不是一堆不相关的属性。

标签: python string class attributes


【解决方案1】:

我认为您正在寻找的一个功能是dirgetattr。这是一个例子

class shopping_cart:
    def __init__(self):
        self.fruits = []
        self.vegetables = []
        self.meat = []
        self.bread = []

    def __str__(self):
        msg = ""
        msg += "shopping cart content\n"
        msg += "---------------------\n"
        members = [attr for attr in dir(self) if not callable(getattr(self, attr)) and not attr.startswith("__")]
        for item in members:
            msg += "---" + item +"-----------: " + str(getattr(self,item) )+"\n"
        return msg

【讨论】:

    【解决方案2】:

    您可以通过以下几种方式做到这一点:

    1 - 使用类的 __dict__ 属性。这为您提供了所有变量的字典对象,您可以遍历它们

    s = shopping_cart()
    s.__dict__
    

    应该输出类似的东西

    {'fruits':[], 'vegetables':[], ... }
    

    2 - 您可以使用列表字典,而不是一堆列表,并在字典上进行迭代。

    3 - 您还可以使用列表列表(例如 [self.fruits, self.vegetables...],然后对其进行迭代。

    【讨论】:

    • 谢谢 Julio,问题是我需要在类本身而不是在实例上做这件事
    • 不客气。那么可能解决方案 2 和 3 最适合您!
    【解决方案3】:

    您可以在类的实例上使用内置的vars() 函数(而不是class 本身):

    class ShoppingCart:
        def __init__(self):
            self.fruits = []
            self.vegetables = []
            self.meat = []
            self.bread = []
    
        def __str__(self):
            msg  = "shopping cart contents\n"
            msg += "----------------------\n"
            for attrname in vars(self):
                value = getattr(self, attrname)
                if isinstance(value, list):
                    msg += "---{}{}: {:2}\n".format(
                                attrname, '-'*(15-len(attrname)), len(value))
            return msg
    
    
    cart = ShoppingCart()
    print(cart)
    

    输出:

    shopping cart contents
    ----------------------
    ---fruits---------:  0
    ---vegetables-----:  0
    ---meat-----------:  0
    ---bread----------:  0
    

    【讨论】:

    • 太棒了!这正是我想要的。非常感谢
    猜你喜欢
    • 1970-01-01
    • 2018-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-30
    • 2016-06-18
    • 1970-01-01
    相关资源
    最近更新 更多