如何将 __format__ 添加到 Python 3.5+ 中的命名元组?

How do I add __format__ to a namedtuple in Python 3.5+?

我正在使用为早期版本 Python 编写的代码。

TensorShape = namedtuple('TensorShape', ['batch_size', 'channels', 'height', 'width'])

稍后,我有这个(删节的)代码:

s = [hdr, '-' * 94]
...
s.append('{:<20} {:<30} {:>20} {:>20}'.format(node.kind, node.name, data_shape,
                                                          tuple(out_shape)))

tuple(out_shape) 上爆炸,但

除外
TypeError: unsupported format string passed to tuple.__format__

因为 out_shape 是一个 TensorShape 并且它没有定义 __format__ 方法。

所以我将 TensorShape 的定义更改为

def format_tensorshape(format_spec):
    return format("{0} {1} {2} {3}")

TensorShape = namedtuple('TensorShape', ['batch_size', 'channels', 'height', 'width'])
TensorShape.__format__ = format_tensorshape

但是这段代码仍然在下游爆炸并出现同样的异常。

我做错了什么?

您走在正确的轨道上——只需连接 two arguments passed to format_tensorshape to your call to format:

import collections
def format_tensorshape(self, format_spec):
    return format("{0} {1} {2} {3}".format(*self), format_spec)

TensorShape = collections.namedtuple('TensorShape', ['batch_size', 'channels', 'height', 'width'])
TensorShape.__format__ = format_tensorshape

out_shape = TensorShape(1,2,3,4)
print('{:>20}'.format(out_shape))

产量

             1 2 3 4

您可以简单地使用基于字符串表示的格式。这可以通过 !s 转换标志实现,因为字符串知道如何解释您的格式规范,因此无需为您的 namedtuple:

创建自定义 __format__ 方法
s.append('{:<20} {:<30} {:>20} {!s:>20}'.format(node.kind, node.name, data_shape,
                                                tuple(out_shape)))
#                               ^^---- here I added the !s

例如:

>>> from collections import namedtuple
>>> TensorShape = namedtuple('TensorShape', ['batch_size', 'channels', 'height', 'width'])
>>> '{!s:>20}'.format(tuple(TensorShape(1,1,1,1)))
'        (1, 1, 1, 1)'