如何将函数调用应用于别名?

0 投票
1 回答
2466 浏览
提问于 2025-04-18 02:29

我的目标是让“过滤”之前定义的节点变得简单。想象一下这个虚构的YAML文件:

%YAML 1.1
---
- fruit: &fruitref { type: banana, color: yellow }
- another_fruit: !rotten *fruitref

我需要在YAML文件或解析这个文件的Python代码中定义什么,才能调用一个自定义函数,并把*fruitref(也就是之前定义的对象,这里是一个映射)作为参数传进去,并得到返回值?我的目标是让“过滤”之前定义的值(映射、序列等等)变得尽可能简单和简洁。

注意

我觉得构造!标签 *别名在YAML中是无效的,因为出现了这个错误:

expected <block end>, but found '<alias>'
  in "/tmp/test.yaml", line 4, column 21

这很可能意味着我无法实现所需的语法,但我确实希望语法尽量简洁(或者说,目标用户会希望这样)。

尝试过的方式

YAML: !!python/object/apply:__main__.rotten [*fruitref]

这个方法可以用,但对于我想要的用途来说太啰嗦了;而且没有必要使用多个参数,使用场景总是是对一个别名(之前定义的映射/序列/对象)的过滤。

YAML: %TAG !f! !!python/object/apply:__main__.

也许!f!rotten [*fruitref]是可以接受的,但我找不到如何使用%TAG指令的方法。
编辑:我发现!!在PyYAML 3.10中不工作,必须使用完整的URL,像这样:%TAG !f! %TAG !f! tag:yaml.org,2002:python/object/apply:__main__.

Python: yaml.add_constructor

我已经在使用add_constructor来“转换”映射为我类的特定实例;但问题是标签别名似乎是无效的YAML。

目前为止最好的方法

add_constructor('!rotten', filter_rotten)在Python中和!rotten [*fruitref]在YAML中似乎可以工作,但我在想是否有可能省略方括号。

1 个回答

0

看起来不能给已经有标签的引用再加标签,所以:

!tag *reference

这样做是不行的。最好的解决办法是把引用放在方括号里(创建一个序列),然后把标签设为一个函数调用或者一个特殊的构造器,这个构造器需要一个对象的序列。这样最简洁的写法就是:

!prefix!suffix [*reference]

或者

!tag [*reference]

撰写回答