Tra*_*ggs 1 python hex python-3.x pprint
我使用了许多类似json的词组.pprint
构建它们很方便.有没有办法使pprint输出中的所有整数以十六进制而不是十进制打印?
例如,而不是:
{66: 'far',
99: 'Bottles of the beer on the wall',
'12': 4277009102,
'boo': 21,
'pprint': [16, 32, 48, 64, 80, 96, 112, 128]}
Run Code Online (Sandbox Code Playgroud)
我宁愿看到:
{0x42: 'far',
0x63: 'Bottles of the beer on the wall',
'12': 0xFEEDFACE,
'boo': 0x15,
'pprint': [0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80]}
Run Code Online (Sandbox Code Playgroud)
我已经尝试过定制PrettyPrinter
,但无济于事,我能够导致上述情况,PrettyPrinter.format()
处理整数似乎只适用于某些整数:
class MyPrettyPrinter(PrettyPrinter):
def format(self, object, context, maxlevels, level):
if isinstance(object, int):
return '0x{:X}'.format(object), True, False
return super().format(object, context, maxlevels, level)
Run Code Online (Sandbox Code Playgroud)
以上课程产生
{0x42: 'far',
0x63: 'Bottles of the beer on the wall',
'12': 0xFEEDFACE,
'boo': 0x15,
'pprint': [16, 32, 48, 64, 80, 96, 112, 128]}
Run Code Online (Sandbox Code Playgroud)
列表内容格式不正确.
您可以更改输出pprint
,但需要重新实现该saferepr()
函数,而不仅仅是类的子pprint.PrettyPrinter()
类.
会发生什么(该内部版本)saferepr()
函数用于所有对象,然后该函数本身递归地处理将对象转换为表示(仅使用自身,而不是PrettyPrinter()
实例),因此任何定制都必须在那里进行.只有当结果saferepr()
变得太大(对于配置的宽度来说太宽)时,PrettyPrinter
类才会开始将容器输出分解成组件以放在单独的行上; saferepr()
然后对组件元素重复调用过程.
所以PrettyPrinter.format()
只负责处理顶级对象,以及每个递归对象,a)在受支持的容器类型(dict,list,tuple,string和这些的标准库子类)中,以及b)其中父表示生产的容器.format()
超出显示宽度.
为了能够覆盖实现,我们需要了解.format()
方法和saferepr()
实现如何交互,它们采用什么参数以及它们需要返回什么.
PrettyPrinter.format()
传递额外的参数context
,maxlevels
和level
:
context
用于检测递归(默认实现返回_recursion(object)
if 的结果id(object) in context
为true).maxlevels
设置level >= maxlevels
为true 且为true,则默认实现将...
作为容器的内容返回.该方法也应该返回3个值的元组; 表示字符串和两个标志.您可以放心地忽略这些标志的含义,它们实际上从未在当前实现中使用.它们用于表示生成的表示是"可读"(使用可传递给的Python语法eval()
)还是递归(对象包含循环引用).但这些 PrettyPrinter.isreadable()
和PrettyPrinter.isrecursive()
方法实际上完全绕过.format()
; 这些返回值似乎是重构破坏了.format()
这两种方法之间的关系.所以,只返回一个字符串,表示与任何你喜欢的两个布尔值.
.format()
真的只是委托内部实现saferepr()
,然后做几件事
context
和深度处理maxlevels
和level
__repr__
方法仍然是默认实现)_safe_tuple
排序键来解决,该键近似于Python 2的排序所有行为.我们可以重复使用它.为了实现递归替换,我更喜欢使用@functools.singledispatch()
委托处理不同类型.忽略自定义__repr__
方法,处理深度问题,递归和空对象,也可以由装饰器处理:
import pprint
from pprint import PrettyPrinter
from functools import singledispatch, wraps
from typing import get_type_hints
def common_container_checks(f):
type_ = get_type_hints(f)['object']
base_impl = type_.__repr__
empty_repr = repr(type_()) # {}, [], ()
too_deep_repr = f'{empty_repr[0]}...{empty_repr[-1]}' # {...}, [...], (...)
@wraps(f)
def wrapper(object, context, maxlevels, level):
if type(object).__repr__ is not base_impl: # subclassed repr
return repr(object)
if not object: # empty, short-circuit
return empty_repr
if maxlevels and level >= maxlevels: # exceeding the max depth
return too_deep_repr
oid = id(object)
if oid in context: # self-reference
return pprint._recursion(object)
context[oid] = 1
result = f(object, context, maxlevels, level)
del context[oid]
return result
return wrapper
@singledispatch
def saferepr(object, context, maxlevels, level):
return repr(object)
@saferepr.register(int)
def _handle_int(object: int, *args):
# uppercase hexadecimal representation with 0x prefix
return f'0x{object:X}'
@saferepr.register(dict)
@common_container_checks
def _handle_dict(object: dict, context, maxlevels, level):
level += 1
contents = [
f'{saferepr(k, context, maxlevels, level)}: '
f'{saferepr(v, context, maxlevels, level)}'
for k, v in sorted(object.items(), key=pprint._safe_tuple)
]
return f'{{{", ".join(contents)}}}'
@saferepr.register(list)
@common_container_checks
def _handle_list(object: list, context, maxlevels, level):
level += 1
contents = [
f'{saferepr(v, context, maxlevels, level)}'
for v in object
]
return f'[{", ".join(contents)}]'
@saferepr.register(tuple)
@common_container_checks
def _handle_tuple(object: tuple, context, maxlevels, level):
level += 1
if len(object) == 1:
return f'({saferepr(object[0], context, maxlevels, level)},)'
contents = [
f'{saferepr(v, context, maxlevels, level)}'
for v in object
]
return f'({", ".join(contents)})'
class HexIntPrettyPrinter(PrettyPrinter):
def format(self, *args):
# it doesn't matter what the boolean values are here
return saferepr(*args), True, False
Run Code Online (Sandbox Code Playgroud)
这个hand-full可以处理基本pprint
实现所能做的任何事情,并且它将在任何受支持的容器中生成十六进制整数.只需创建一个HexIntPrettyPrinter()
类的实例并调用.pprint()
它:
>>> sample = {66: 'far',
... 99: 'Bottles of the beer on the wall',
... '12': 4277009102,
... 'boo': 21,
... 'pprint': [16, 32, 48, 64, 80, 96, 112, 128]}
>>> pprinter = HexIntPrettyPrinter()
>>> pprinter.pprint(sample)
{0x42: 'far',
0x63: 'Bottles of the beer on the wall',
'12': 0xFEEDFACE,
'boo': 0x15,
'pprint': [0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80]}
Run Code Online (Sandbox Code Playgroud)
旁注:从Python 3.7开始,您可以删除装饰器的(<type>)
调用部分@saferepr.registation(<type>)
; 该类型是从注释中获取的.
归档时间: |
|
查看次数: |
383 次 |
最近记录: |