创建__repr__打印子类数据

Creating __repr__ to print subclass data

我想创建一个基础 class,它具有所有子级都继承的属性,并且还有一个描述性的 __repr__ 方法。以下内容是否可以接受?

from collections import Counter

class Component:
    cnt = Counter()
    def __init__(self, _type, **kwargs):
        Component.cnt[_type] += 1
        self.type = _type
        self.identifier = f'{self.type[0]}{Component.cnt[_type]}'
        self._kwargs = kwargs
    def __repr__(self):
        s = f'{self.__class__.__name__}('
        for k, v in self._kwargs.items():
            s += f'{k}={v!r}, '
        s = s.strip(', ') + f') # identifier: {self.identifier}'
        return s

class Battery(Component):
    # outbound is positive terminal
    def __init__(self, voltage):
        super().__init__(self.__class__.__name__, voltage=voltage)
        self.voltage = voltage

>>> b=Battery(9)
>>> b
Battery(voltage=9) # identifier: B1

具体来说,self._kwargs 看起来像黑客吗?什么可能是更好的方法呢?或者,是否有比我目前正在做的更好、更 pythonic 的方式来完成上述操作?

不需要将self.__class__.__name__传递给super().__init__ - superclass的__init__方法可以直接访问它,就像你的[=15一样=]方法即可。所以 self.type 属性是多余的。

下面是在基class中写__repr__的一种合理方式:不用你自己的_kwargs属性,你可以使用对象自己的__dict__。这包括 identifier 属性,因此您无需单独添加。

from collections import Counter

class Component:
    cnt = Counter()
    def __init__(self, **kwargs):
        _type = self.__class__.__name__
        Component.cnt[_type] += 1
        self.identifier = _type[0] + str(Component.cnt[_type])
        super().__init__(**kwargs) # co-operative subclassing
    def __repr__(self):
        return '{0}({1})'.format(
            self.__class__.__name__,
            ', '.join(
                '{0}={1!r}'.format(k, v)
                for k, v in self.__dict__.items()))

class Battery(Component):
    # outbound is positive terminal
    def __init__(self, *, voltage, **kwargs):
        self.voltage = voltage
        super().__init__(**kwargs) # co-operative subclassing

示例:

>>> b = Battery(voltage=9) # keyword-only argument for co-operative subclassing
>>> b
Battery(voltage=9, identifier='B1')

我用关于 co-operative subclassing 的评论标记了一些代码。在 class 层次结构中,每个 __init__ 方法都可以将其参数作为关键字,并将其 **kwargs 传递给 super().__init__ 方法,这样您就不必编写相同的方法classes.

中多次使用参数名称

如果您使用多重继承,调用 super().__init__ 也很重要。即使您不使用多重继承,这也会调用 object.__init__,它具有确保没有 "unused" 参数未被另一个 __init__ 方法处理的巧妙效果。