Передача аргументов в tp_new и tp_init из подтипов в Python C API
Первоначально я задал этот вопрос в списке capi-sig Python:Как передать аргументы в tp_new и tp_init из подтипов?
Я читаю PythonPEP-253 на подтип и есть много хороших рекомендаций о том, как структурировать типы, звонитеtp_new
а такжеtp_init
слоты и т. д.
Но в нем отсутствует важное примечание о передаче аргументов из sub в супертип. КажетсяPEP-253 незакончен согласно примечанию:
(XXX There should be a paragraph or two about argument passing here.)
Итак, я пытаюсь экстраполировать некоторые стратегиихорошо известно из подтипов классов Pythonособенности техник, которые на каждом уровне снимают аргументы и т. д.
Я ищу методы для достижения подобного эффекта, но использую простойPython 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)
Что будет эквивалентно в Python C API?
Как бороться с подобной ситуацией, но с аргументами, специфичными для производного класса, ожидаемого в другом порядке?
Это аргументы, данные в конце кортежа args (илиkwds
dict, я полагаю, принцип будет таким же).
Вот некоторый (псевдо) код, который иллюстрирует ситуацию:
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):
Обратите внимание, еслиa
ожидалось сначала:
Derived.__init__(self, a, x, y)
это было бы похоже на ситуациюShape
а такжеColoredShape
выше.
Я думаю, было бы легче иметь дело с этим.
Может ли кто-нибудь помочь разобраться с пропавшим без вести?XXX комментарий, упомянутый выше, и правильная техника для передачи аргументов от подтипа до супертипа (ов) в конструкции?
ОБНОВЛЕНИЕ 2012-07-17:
Вдохновленныйответ Ecatmur ниже я просмотрел источники Python 3 и нашелdefdict_init
конструкторcollections.defaultdict Тип объекта интересный. Тип является производным отPyDictObject
и его конструктор принимает дополнительный аргументdefault_factory
, Подпись конструктора в классе Python такова:
class collections.defaultdict([default_factory[, ...]])
Теперь вот какdefault_factory
снято с оригиналаargs
кортеж, поэтому остальные аргументы направляютсяtp_init
базового типа, этоPyDictObject
:
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);
Обратите внимание, это урезанное присутствие только соответствующей частиdefdict_init
функция.