私はadd_constructor
で追加できる適切なコンストラクタ関数を定義する方法を理解するために、PyYAMLソースコードを読んできました。私はそのコードが今どのように動作しているかをよく理解していますが、なぜSafeConstructor
のデフォルトのYAMLコンストラクタがジェネレータであるのか理解できません。例えば、方法SafeConstructor
のconstruct_yaml_map
:なぜPyYAMLはジェネレータを使ってオブジェクトを構築しますか?
def construct_yaml_map(self, node):
data = {}
yield data
value = self.construct_mapping(node)
data.update(value)
私はオブジェクトをスタブのみdeep=False
がconstruct_mapping
に渡された場合、ノードからデータを移入するために次のように発電機がBaseConstructor.construct_object
に使用される方法を理解する。
if isinstance(data, types.GeneratorType):
generator = data
data = generator.next()
if self.deep_construct:
for dummy in generator:
pass
else:
self.state_generators.append(generator)
BaseConstructor.construct_document
のデータはdeep=False
の場合、construct_mapping
の場合はどのように生成されるのか分かります。私は理解していない何
def construct_document(self, node):
data = self.construct_object(node)
while self.state_generators:
state_generators = self.state_generators
self.state_generators = []
for generator in state_generators:
for dummy in generator:
pass
は、データオブジェクトをスタブとconstruct_document
に発電機を反復して、オブジェクトを下に作業の利益です。これはYAML仕様の中で何かをサポートするために行わなければならないのですか、それともパフォーマンス上の利点をもたらしますか?
This answer on another questionはやや役立ったが、私はその答えは、このない理由を理解していない。これに代えて
def foo_constructor(loader, node):
instance = Foo.__new__(Foo)
yield instance
state = loader.construct_mapping(node, deep=True)
instance.__init__(**state)
:
def foo_constructor(loader, node):
state = loader.construct_mapping(node, deep=True)
return Foo(**state)
を、私は後者の形式は、のために働くことをテストしてみました例はその他の答えに掲載されていますが、おそらく私はいくつかの端の場合がありません。
PyYAMLのバージョン3.10を使用していますが、問題のコードがPyYAMLの最新バージョン(3.12)で同じであるようです。
ようこそStackoverflow。 – Randy