覆盖__repr__或pprint for int

时间:2016-08-23 07:47:47

标签: python python-3.x built-in

有没有办法在调用intrepr时更改pprint.pformat类型对象转换为字符串的方式,这样

repr(dict(a=5, b=100))

会提供"{a: 0x5, b: 0x64}"而不是"{a: 5, b: 100}"吗?

我认为继承int类型是一个选项:

class IntThatPrintsAsHex(int):
    def __repr__(self):
        return hex(self)

def preprocess_for_repr(obj):
    if isinstance(obj, dict):
        return {preprocess_for_repr(k): preprocess_for_repr(v) for k, v in obj.items()}
    elif isinstance(obj, list):
        return [preprocess_for_repr(e) for e in obj]
    elif isinstance(obj, tuple):
        return tuple(preprocess_for_repr(e) for e in obj)
    elif isinstance(obj, int) and not isinstance(obj, bool):
        return IntThatPrintsAsHex(obj)
    elif isinstance(obj, set):
        return {preprocess_for_repr(e) for e in obj}
    elif isinstance(obj, frozenset):
        return frozenset(preprocess_for_repr(e) for e in obj)
    else:  # I hope I didn't forget any.
        return obj

print(repr(preprocess_for_repr(dict(a=5, b=100))))

但正如您所看到的,preprocess_for_repr功能相当令人不愉快,以保持" as-complete-as-needed"并与之合作。此外,明显的性能影响。

2 个答案:

答案 0 :(得分:2)

int是内置类型,您无法设置内置/扩展类型的属性(您不能覆盖也不能为这些类型添加新方法)。但是,您可以继承int并覆盖__repr__方法,如下所示:

 class Integer(int):
     def __repr__(self):
         return hex(self)

 x = Integer(3)
 y = Integer(100)

 # prints "[0x3, 0x64]"
 print [x,y]
除了Integer方法之外,

__repr__的行为与int完全相同。你可以使用它的索引列表,做数学等等。但是,除非您覆盖它们,否则数学运算将返回常规的int结果:

>>> print [x,y,x+1,y-2, x*y]
[0x3, 0x64, 4, 98, 300]

答案 1 :(得分:1)

你应该能够修补pprint模块以使整数以你想要的方式打印,但这不是一个好方法。

如果您只是想要更好地表示调试整数,IPython有自己的漂亮打印机,可以通过pretty模块轻松定制:

In [1]: from IPython.lib import pretty

In [2]: pretty.for_type(int, lambda n, p, cycle: p.text(hex(n)))
Out[2]: <function IPython.lib.pretty._repr_pprint>

In [3]: 123
Out[3]: 0x7b

In [4]: x = [12]

In [5]: x
Out[5]: [0xc]

In [6]: pretty.pretty(x)
Out[6]: '[0xc]'

您可以在链接文档中阅读有关这三个参数的更多信息。