将namedtuple的__str__和__repr__行为带到常规类

时间:2017-01-11 21:24:25

标签: python namedtuple repr

Twilio Sync

我一直认为namedtuple内置__str____repr__非常整洁,我正在寻找一种简单的方法将其应用于我的任何类别。

>>> from collections import namedtuple
>>> A  = namedtuple("A", ["foo"])
>>> print(A(foo=1))
A(foo=1)
>>> str(A(foo=1))
'A(foo=1)'
>>> repr(A(foo=1))
'A(foo=1)'

修改

我最初是从一堆冗长而非动态的硬编码__repr__开始的。我不喜欢那样。 namedtuple可以自动完成它。

def __repr__(self):
    return 'className(attrA={attrA}, attrB={attrB})'.format(**vars(self)))

4 个答案:

答案 0 :(得分:6)

有点hacky但这样做:

from collections import namedtuple

def nice_repr(obj):
    def nice_repr(self):
        return repr(
            namedtuple(
                type(self).__name__,
                vars(self)
            )(**vars(self))
        )

    obj.__repr__ = nice_repr

    return obj

示例:

@nice_repr
class A:
    def __init__(self, b, c):
        self.b = b
        self.c = c

print(repr(A(1, 2)))  # Outputs: A(c=2, b=1)

编辑:(自动防故障版)

def nice_repr(obj):
    """ Decorator to bring namedtuple's __repr__ behavior to regular classes. """

    def nice_repr(self):
        v = vars(self)

        # Prevent infinite looping if `vars` happens to include `self`.
        del(v['self'])

        return repr(namedtuple(type(self).__name__, v)(**v))

    obj.__repr__ = nice_repr

    return obj

答案 1 :(得分:1)

如果我是你,我会创建一个带有__repr__方法定义的父类,并在子类中继承该类以具有该行为。对我来说,your solution看起来像是一个巨大的黑客,以实现非常微不足道的事情。以下是样本:

class BaseClass:

     # logic can be used with in `__repr__` itself.
     # creating separate function to make it more clear
     def _get_formatted_string(self):
         return '{class_name}({params})'.format(
             class_name=self.__class__.__name__,
             params=', '.join('{}={}'.format(k, v) for k, v in vars(self).items()))

     def __repr__(self):
         return self._get_formatted_string()

class child(BaseClass):

    def __init__(self, a, b):
        self.a = a
        self.b = b

这是理想的行为:

>>> c = child(1, 2)
>>> repr(c)
'child(a=1, b=2)'
>>> str(c)
'child(a=1, b=2)'

答案 2 :(得分:1)

键入。NamedTuple新颖而优雅。更好的collections.namedtuple版本。

from typing import NamedTuple

class Employee(NamedTuple):
    name: str
    id: int

基本相同
Employee = collections.namedtuple('Employee', ['name', 'id'])

此问题的更高级示例

from typing imoprt NamedTuple

class Employee(NamedTuple):
    """Represents an employee."""
    name: str
    id: int = 3

    def __repr__(self) -> str:
        return f'<Employee {self.name}, id={self.id}>'

请参阅https://docs.python.org/3/library/typing.html#typing.NamedTuple

答案 3 :(得分:-1)

创建任何类时,您定义自己的__str__函数就像创建__init__函数一样

class Foo:
    def __init__(self):
        self.a="value"

    def __str__(self):
        return "a is: "+self.a

variable=Foo()
print variable

这将打印:&#34; a是:值&#34; 你可以为任何一个班级做到这一点