/ / Ładowanie nieskończenie zagnieżdżonych krotek z YAML - python, zagnieżdżone, yaml, samodzielne

Ładowanie nieskończenie zagnieżdżonych krotek z YAML - python, nested, yaml, self-contained

Poniższy kod generuje nieskończenie zagnieżdżoną listę python:

import yaml
i_list = yaml.load("&id1 [3, *id1]")
print i_list
# [3, [...]]
print i_list[1] is i_list
# True

Mogę również wyraźnie wspomnieć o pytonie list rodzaj:

i_list = yaml.load("&id1 !!python/list [3, *id1]")

Mogę również ręcznie utworzyć tę strukturę bez analizowania yaml, w następujący sposób:

i_list = [3]
i_list.append(i_list)

Jednak ostatnia sztuczka nie działała dla krotek ani żadnego innego niezmiennego obiektu. Aby utworzyć krotkę z nieskończenie zagnieżdżonym interfejsem, muszę użyć interfejsu API CPython:

from ctypes import pythonapi
from _ctypes import PyObj_FromPtr

t = pythonapi.PyTuple_New(1)
pythonapi.PyTuple_SetItem(t, 0, t)
i_tup = PyObj_FromPtr(t)
print repr(i_tup)
# ((...),)

Oczekiwany kod yaml dla takiej krotki wyglądałby tak:

&id001 !!python/tuple
- *id001

i rzeczywiście, to jest wynik yaml.dump(i_tup). Jednak yaml Pythona nie może załadować tego samego kodu:

yaml.load(yaml.dump(i_tup))

ConstructorError: found unconstructable recursive node
in "<string>", line 1, column 1:
&id001 !!python/tuple
^

Jest jakiś dobry powód, dlaczego tak jest? Jakieś obejście, które możesz zasugerować?

Odpowiedzi:

4 dla odpowiedzi № 1

Krotki po prostu nie są do tego przeznaczone. Nie ma sposobu na zbudowanie czegoś takiego za pomocą zwykłego API Pythona, a nawet C API który pozwala ominąć to ma czek (op->ob_refcnt != 1), który bardzo może popsuć się, jeśli spróbujesz:

int
PyTuple_SetItem(register PyObject *op, register Py_ssize_t i, PyObject *newitem)
{
register PyObject *olditem;
register PyObject **p;
if (!PyTuple_Check(op) || op->ob_refcnt != 1) {
Py_XDECREF(newitem);
PyErr_BadInternalCall();
return -1;
}
...
}

Jeśli spróbujesz ustawić przy tym dowolne elementy krotkiPo umieszczeniu odnośnika, Python wykrywa odnośnik jako błąd. Twórz krotki w ten sposób na własne ryzyko i nie zdziw się, jeśli Twój kod zepsuje się z dziwnych powodów.