Przekazywanie argumentów do tp_new i tp_init z podtypów w Python C API
Pierwotnie zadałem to pytanie na liście capi-sig Pythona:Jak przekazać argumenty do tp_new i tp_init z podtypów?
Czytam PythonaPEP-253 na temat podtypów i istnieje wiele dobrych zaleceń na temat struktury typów, zadzwońtp_new
itp_init
automaty itp.
Brakuje jednak ważnej notatki dotyczącej przekazywania argumentów z sub do super typu. Wydaje sięPEP-253 jest niedokończone zgodnie z uwagą:
(XXX Powinien być akapit lub dwa o przekazywaniu argumentów tutaj.)
Próbuję więc ekstrapolować niektóre strategiedobrze znany z podtypowania klas Pythona, zwłaszcza techniki, w których każdy poziom usuwa argumenty itp.
Szukam technik, aby osiągnąć podobny efekt, ale używając zwykłegoPython C API (3.x):
class Shape:
def __init__(self, shapename, **kwds):
self.shapename = shapename
super().__init__(**kwds)
class ColoredShape(Shape):
def __init__(self, color, **kwds):
self.color = color
super().__init__(**kwds)
Jaki byłby odpowiednik w Python C API?
Jak radzić sobie z podobną sytuacją, ale z oczekiwanymi argumentami specyficznymi dla klasy pochodnej w innej kolejności? Jest to argumenty podane na końcu krotki argumentów (lubkwds
Dict, zakładam, że zasada będzie taka sama.
Oto kod (pseudo) ilustrujący sytuację:
class Base:
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
class Derived(Base):
def __init__(self, x, y, a):
self.a = a
super().__init__(x, y, None):
Uwaga, jeślia
oczekiwano najpierw:
Derived.__init__(self, a, x, y)
byłaby podobna sytuacja doShape
iColoredShape
powyżej. Zakładam, że łatwiej byłoby sobie z tym poradzić.
Czy ktoś mógłby pomóc w odnalezieniu zaginionegoXXX wspomniany powyżej komentarz i poprawna technika przekazywania argumentów z podtypu do super typu (ów) w konstrukcji?
AKTUALIZACJA 2012-07-17:
Zainspirowany przezodpowiedź ecatmur poniżej przejrzałem źródła Pythona 3 i znalazłemdefdict_init
konstruktorcollections.defaultdict obiekt typu interesujący. Typ pochodzi odPyDictObject
a jego konstruktor przyjmuje dodatkowy argumentdefault_factory
. Podpis konstruktora w klasie Pythona jest następujący:
class collections.defaultdict([default_factory[, ...]])
Oto jakdefault_factory
jest pozbawiony oryginałuargs
krotka, więc pozostałe argumenty są przekazywane dotp_init
typu podstawowegoPyDictObject
:
int result;
PyObject *newargs;
Py_ssize_t n = PyTuple_GET_SIZE(args);
...
newargs = PySequence_GetSlice(args, 1, n);
...
result = PyDict_Type.tp_init(self, newargs, kwds);
Uwaga: ta wycięta obecność dotyczy tylko odpowiedniej częścidefdict_init
funkcjonować.