我打算将 PyYAML 用于配置文件。该配置文件中的一些项目是元组的 Python 元组。所以,我需要一种方便的方式来表示它们。使用 PyYAML 可以如下表示元组的 Python 元组
print yaml.load("!!python/tuple [ !!python/tuple [1, 2], !!python/tuple [3, 4]]")
但是,对于长序列的项目,这不是方便的表示法。我认为应该可以定义一个自定义标签,比如 python/tuple_of_tuples。即类似的东西
yaml.load("!!python/tuple_of_tuples [[1,2], [3,4]]")
请参阅下面我第一次尝试定义它,通过模仿 python/tuple 的定义方式,并尝试进行类似的子类化。它失败了,但我想知道我在追求什么。我有第二次尝试,但它是作弊,因为它只是调用eval
.
如果我找不到更好的东西,我会使用它。但是,YAML 旨在替代使用 INI 文件的 ConfigObj,它的功能远不如 YAML,我eval
对元组的元组使用了相同的方法(即 )。所以在这方面它不会更糟。
一个适当的解决方案将是最受欢迎的。
我对我的第一个解决方案有几点意见。
我原以为构造函数
construct_python_tuple_of_tuples
会返回完整的结构,但实际上它似乎返回一个空结构,如下所示([], [])
我跟踪了这些调用,调用之后似乎发生了很多复杂的事情
construct_python_tuple_of_tuples
。返回的值是整数列表的元组,因此非常接近所需的结果。因此,结构必须稍后完成。
该行与
tuple([tuple(t) for t in x])
是我试图将元组列表强制为元组的元组,但如果我从 中返回它
construct_python_tuple_of_tuples
,那么结果调用yaml.load("!!python/tuple_of_tuples [[1,2], [3,4]]")
就是((),())
不知道是什么
yaml.org,2002
为什么是 2002 年?
第一次尝试
import yaml
from yaml.constructor import Constructor
def construct_python_tuple_of_tuples(self, node):
# Complete content of construct_python_tuple
# is
# return tuple(self.construct_sequence(node))
print "node", node
x = tuple(self.construct_sequence(node))
print "x", x
foo = tuple([tuple(t) for t in x])
print "foo", foo
return x
Constructor.construct_python_tuple_of_tuples =
construct_python_tuple_of_tuples
Constructor.add_constructor(
u'tag:yaml.org,2002:python/tuple_of_tuples',
Constructor.construct_python_tuple_of_tuples)
y = yaml.load("!!python/tuple_of_tuples [[1,2], [3,4]]")
print "y", y, type(y)
print y[0], type(y[0])
print y[0][0], type(y[0][0])
结果是
node SequenceNode(tag=u'tag:yaml.org,2002:python/tuple_of_tuples',
value=[SequenceNode(tag=u'tag:yaml.org,2002:seq',
value=[ScalarNode(tag=u'tag:yaml.org,2002:int', value=u'1'),
ScalarNode(tag=u'tag:yaml.org,2002:int', value=u'2')]),
SequenceNode(tag=u'tag:yaml.org,2002:seq',
value=[ScalarNode(tag=u'tag:yaml.org,2002:int', value=u'3'),
ScalarNode(tag=u'tag:yaml.org,2002:int', value=u'4')])])
x ([], [])
foo ((), ())
y ([1, 2], [3, 4]) <type 'tuple'>
y[0] [1, 2] <type 'list'>
y[0][0] 1 <type 'int'>
第二次尝试
import yaml
from yaml import YAMLObject, Loader, Dumper
class TupleOfTuples(YAMLObject):
yaml_loader = Loader
yaml_dumper = Dumper
yaml_tag = u'!TupleOfTuples'
#yaml_flow_style = ...
@classmethod
def from_yaml(cls, loader, node):
import ast
print "node", node
print "node.value", node.value, type(node.value)
return ast.literal_eval(node.value)
@classmethod
def to_yaml(cls, dumper, data):
return node
t = yaml.load("!TupleOfTuples ((1, 2), (3, 4))")
print "t", t, type(t)
结果是:
node ScalarNode(tag=u'!TupleOfTuples', value=u'((1, 2), (3, 4))')
node.value ((1, 2), (3, 4)) <type 'unicode'>
t ((1, 2), (3, 4)) <type 'tuple'>