我同样的问题,因为这个问题跑了不能升级,我是不是太满意两个答案。在浏览pyyaml文档时,我发现 真的有两种有趣的方法:yaml.add_constructor和yaml.add_implicit_resolver。
隐式解析器解决了通过将字符串与正则表达式进行匹配来标记具有!!python/tuple的所有条目的问题。我也想使用元组语法,所以编写tuple: (10,120)而不是写一个列表tuple: [10,120]然后把 转换成元组,我个人觉得非常烦人。我也不想安装外部库。下面是代码:
import yaml
import re
# this is to convert the string written as a tuple into a python tuple
def yml_tuple_constructor(loader, node):
# this little parse is really just for what I needed, feel free to change it!
def parse_tup_el(el):
# try to convert into int or float else keep the string
if el.isdigit():
return int(el)
try:
return float(el)
except ValueError:
return el
value = loader.construct_scalar(node)
# remove the () from the string
tup_elements = value[1:-1].split(',')
# remove the last element if the tuple was written as (x,b,)
if tup_elements[-1] == '':
tup_elements.pop(-1)
tup = tuple(map(parse_tup_el, tup_elements))
return tup
# !tuple is my own tag name, I think you could choose anything you want
yaml.add_constructor(u'!tuple', yml_tuple_constructor)
# this is to spot the strings written as tuple in the yaml
yaml.add_implicit_resolver(u'!tuple', re.compile(r"\(([^,\W]{,},){,}[^,\W]*\)"))
最后通过执行此:
>>> yml = yaml.load("""
...: cities:
...: 1: (0,0)
...: 2: (4,0)
...: 3: (0,4)
...: 4: (4,4)
...: 5: (2,2)
...: 6: (6,2)
...: highways:
...: - (1,2)
...: - (1,3)
...: - (1,5)
...: - (2,4)
...: - (3,4)
...: - (5,4)
...: start: 1
...: end: 4""")
>>> yml['cities']
{1: (0, 0), 2: (4, 0), 3: (0, 4), 4: (4, 4), 5: (2, 2), 6: (6, 2)}
>>> yml['highways']
[(1, 2), (1, 3), (1, 5), (2, 4), (3, 4), (5, 4)]
有可能是同一个save_load潜在的缺点相比load我没有测试。