我计划使用PyYAML作为配置文件。一些项目 在这个配置文件中是Python元组的元组。所以,我需要一个 方便的表达方式。可以表示 使用PyYAML的元组如下
print yaml.load("!!python/tuple [ !!python/tuple [1, 2], !!python/tuple [3, 4]]")
但是,对于长序列的 项目。我认为应该可以定义一个自定义标记,比如 python/元组的元组。一、 e.类似的东西
^{pr2}$请看下面我第一次尝试通过模仿
定义了python/tuple,并尝试进行类似的子类化。它
失败了,但我想我知道我在找什么。我还有时间
尝试这样做是有效的,但这是一个欺骗,因为它只调用eval
。在
如果我找不到更好的东西,我就用它。然而,YAML
作为ConfigObj的替代品,ConfigObj使用INI文件,并且
远不如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'>
首先从问题2开始:2002年是2002年9月1日在YAML 1.0 draft版本中引入这种标记的年份
问题1更复杂。如果您这样做:
你得到(A):
^{pr2}$但实际上这是(B)的缩写:
是(C)的缩写:
A、B和C都加载到列表的原始列表中,因为序列是一个内置类型。在
我不认为扩展yaml的语法(例如
()
表示元组)是个好主意。要最小化标记,请将示例简化为:并添加一个构造函数:
但这将问题推到创建
construct_tuple
函数上。一个序列(在constructor.py
)中是:但是你不能仅仅用
[]
替换其中的[]
,因为通过扩展元组来改变元组是行不通的(使用yield
来改变元组的这种两步创建的原因,例如允许在诸如sequence和mapping这样的复杂类型中进行循环引用)。在您应该定义一个
Tuple()
类,该类的行为类似于list,直到“locked”(在构造结束时会这样做),从那时起,它的行为应该类似于元组(即不再修改)。下面的方法没有子类化yaml.YAMLObject
,因此必须显式地为类提供并注册构造函数和resenter。在有了它,您可以:
获得:
这不是一个真正的
tuple
,但它不允许list
类操作。以下活动都会引发相应的错误:最后你可以:
对于以下输出:
如果您真的希望
!tuple [[1, 2], [3, 4]]
创建一个元组的元组,可以通过在yaml
的Baseloader
类中保持上下文状态,并根据上下文重写从序列到元组或列表构造python对象的方法。这可能必须是一堆上下文状态,以允许嵌套使用!当使用!!seq
作为标记时,使用一些显式重写来获取元组中的列表。在我可能没有检查}相比的限制。
Tuple()
的完整性,只实现了tuple
与立即想到的{我用PyYAML的增强版本进行了测试:ruamel.yaml,但是这在PyYAML本身中应该是一样的。在
相关问题 更多 >
编程相关推荐