[英]How to remove a key/value pair from yaml dump, in Python?
Suppose I have a naive class definition: 假设我有一个天真的类定义:
import yaml
class A:
def __init__(self):
self.abc = 1
self.hidden = 100
self.xyz = 2
def __repr__(self):
return yaml.dump(self)
A()
printing 印花
!!python/object:__main__.A
abc: 1
hidden: 100
xyz: 2
Is there a clean way to remove a line containing hidden: 100
from yaml dump's printed output? 是否有一种干净的方法从yaml dump的打印输出中删除包含hidden: 100
的行? The key name hidden
is known in advance, but its numeric value may change. hidden
的密钥名称是预先知道的,但其数值可能会更改。
Desired output: 期望的输出:
!!python/object:__main__.A
abc: 1
xyz: 2
FYI: This dump is for display only and will not be loaded. 仅供参考:此转储仅供显示,不会加载。
I suppose one can suppress key/value pair with key= hidden
with use of yaml.representative
. 我想可以使用yaml.representative
来使用key = hidden
来抑制键/值对。 Another way is find hidden: [number]
with RegEx in a string output. 另一种方法是查找hidden: [number]
在字符串输出中使用RegEx。
I looked at the documentation for pyyaml and did not find a way to achieve your objective. 我查看了pyyaml的文档,但没有找到实现目标的方法。 A work-around would be to delete the attribte hidden
, call yaml.dump
, then add it back in: 解决方法是删除hidden
的attribte,调用yaml.dump
,然后将其添加回:
def __repr__(self):
hidden = self.hidden
del self.hidden
return yaml.dump(self)
self.hidden = hidden
Taking a step back, why do you want to use yaml
for __repr__
? 退后一步,你为什么要使用yaml
作为__repr__
? Can you just roll your own instead of relying on yaml
? 你可以自己滚动而不是依靠yaml
吗?
json
is mature solution and (at the moment of writing) have much better docs than pyyaml
; json
是成熟的解决方案,并且(在写作的那一刻)有比pyyaml
更好的文档;
I'd use it instead while pyyaml
's docs are hard to fully understand. 我会使用它,而pyyaml
的文档很难完全理解。 As a bonus, YAML is (almost) superset of JSON, so you'll be able to read your data as YAML without converting it. 作为奖励,YAML(几乎)是JSON的超集,因此您将能够在不转换数据的情况下将您的数据读取为YAML。
However, to easily use all goodies of YAML you will probably have to convert the data to YAML 但是,要轻松使用YAML的所有好东西,您可能必须将数据转换为YAML
json
module is unable to serialize custom objects by default, but it can be easily extended: 默认情况下, json
模块无法序列化自定义对象,但可以轻松扩展:
import json
def default(o):
if isinstance(o, A):
result = vars(o).copy()
del result['hidden']
result['__class__'] = o.__class__.__name__
return result
else:
return o
json.dumps(A(), default=default) # => '{"__class__": "A", "xyz": 2, "abc": 1}'
If you don't want to write default=default
everywhere you dumps
, you can create custom serializer: 如果您不想在dumps
任何位置写入default=default
,则可以创建自定义序列化程序:
dumper = json.JSONEncoder(default=default)
dumper.encode(A()) # => '{"__class__": "A", "xyz": 2, "abc": 1}'
Or, to be able to easily extend it even further via subclassing: 或者,通过子类化可以轻松地进一步扩展它:
class Dumper(json.JSONEncoder):
__slots__ = ()
def default(self, o):
if isinstance(o, A):
result = vars(o).copy()
del result['hidden']
result['__class__'] = o.__class__.__name__
return result
else:
return super().default(o)
dumper = Dumper()
dumper.encode(A()) # => '{"__class__": "A", "xyz": 2, "abc": 1}'
Note that fields in JSON are unordered. 请注意,JSON中的字段是无序的。
Also, if you want to use this, I'd advise you not to serialize dict with key __class__
, because it might be hard to distinguish it from serialized object. 另外,如果你想使用它,我建议你不要用密钥__class__
序列化dict,因为它可能很难将它与序列化对象区分开来。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.