简体   繁体   English

对每个类的__str__使用每个实例属性的__str__

[英]Use __str__ of each instance attribute for a class's __str__

Is there a way in Python 3 to recursively call private member variables unique __str__ functions programmatically? 有没有办法在Python 3中以编程方式递归调用私有成员变量__str__函数? Something like: 就像是:

class A:
  def __str__(self):
    return "A"

class B:
  def __str__(self):
    return "B"

class C:
  def __init__(self):
    self._A = A()
    self._B = B()

  def __str__(self):
    for var in vars(self):
      return str(var)

When calling the individual private members, it works fine. 在呼叫个人私人会员时,它运作正常。 Would like a method to do it dynamically however. 想要一种动态地做它的方法。

Thanks so much. 非常感谢。

The vars function returns a dictionary where the keys are the variable names (as strings) and the values are the values of the variable. vars函数返回一个字典,其中键是变量名(作为字符串),值是变量的值。 So iterating over the values should work. 所以迭代这些值应该有效。

class A:
  def __str__(self):
    return "A"

class B:
  def __str__(self):
    return "B"

class C:
  def __init__(self):
    self._A = A()
    self._B = B()

  def __str__(self):
    output = ""
    for _,var in vars(self).items(): #Iterate over the values
      output += str(var) #Use the str() function here to make the object return its string form
    return output #Need to return instead of print since that is what the __str__() function should do

You can add some kind of separator (like a \\n ) between the values if you want. 如果需要,可以在值之间添加某种分隔符(如\\n )。 Just replace str(var) with str(var) + "\\n" . 只需用str(var) + "\\n"替换str(var)

You can also use the dictionary keys; 你也可以使用字典键; vars() is self.__dict__ : vars()self.__dict__

>>> class A:
...     def __str__(self):
...         return self.__class__.__name__
... 
>>> class B:
...     def __str__(self):
...         return self.__class__.__name__
... 
>>> str(A())
'A'
>>> repr(A())  # "long-form" the hex-string is id()
'<__main__.A object at 0x10f65a908>'

>>> class C:
...     def __init__(self):
...        self.A = A()
...        self.B = B()
...     def __str__(self):
...         return '\n'.join(self.__dict__)
... 
>>> C()
<__main__.C object at 0x10f65aa58>
>>> print(C())  # Uses str(C())
A
B

vars(self) is effectively self . vars(self)是有效的self In turn, self.__dict__ is a dict used to store an object's (writable) attributes. 反过来, self.__dict__是一个用于存储对象(可写)属性的dict

>>> C().__dict__
{'A': <__main__.A object at 0x10f65aa90>, 'B': <__main__.B object at 0x10f65aac8>}

The signature is '\\n'.join(iterable) , and when you iterate over a dictionary, you iterate over its keys, which suffices in this case. 签名是'\\n'.join(iterable) ,当你遍历字典时,你迭代它的键,在这种情况下就足够了。

Note on Dataclasses 关于数据类的注意事项

I'm not totally sure if (Python 3.7+) dataclasses are an easier solution here. 我不完全确定(Python 3.7+)数据类是否是一个更简单的解决方案。 That's because they automatically implement a __repr__() but not a __str__() as far as I can tell: 那是因为他们自动实现__repr__()而不是__str__() ,据我所知:

>>> from dataclasses import dataclass
>>>
>>> @dataclass
... class C:
...     _A: object = A()
...     _B: object = B()
... 
>>> c = C()  # still uses repr() for each field
>>> str(c)
'C(_A=<__main__.A object at 0x10f373828>, _B=<__main__.B object at 0x10f373940>)'

In other words, you'd need to replace A.__str__ with A.__repr__ (same for B , which is maybe not something you want to do in the first place with regards to those two classes.) 换句话说,你需要用A.__str__替换A.__str__ A.__repr__ (对于B来说也是如此,对于这两个类,这可能不是你想要做的事情。)

Are you sure you shouldn't be using __repr__ ? 你确定你不应该使用__repr__吗?

Anyway, here's an example using attrs , beacuse I'm stuck on Python 3.5. 无论如何,这是一个使用attrs的例子,因为我坚持使用Python 3.5。 With dataclasses it will work in a similar manner. 使用dataclasses ,它将以类似的方式工作。

import attr


class A:
    def __str__(self):
        return 'A'

class B:
    def __str__(self):
        return 'B'

@attr.s
class C:
    a = attr.ib(default=attr.Factory(A))
    b = attr.ib(default=attr.Factory(B))


if __name__ == '__main__':
    c = C()
    print(c) # __str__ defaults to __repr__

    def __str__(self):
        bits = ['<C']
        for a in self.__attrs_attrs__:
            bits.append(' %s=%s' % (a.name, getattr(self, a.name)))
        bits.append('>')
        return ''.join(bits)
    C.__str__ = __str__
    print(c) # custom __str__

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

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