Передача аргументов в tp _new и tp _init из подтипов в Python C API

Изначально я задал этот вопрос в сиг-листе Python capi -:. Как передать аргументы в tp _new и tp _init из подтипов?

Я читаю Python PEP -253 о подтипах, и там есть много хороших рекомендаций о том, как структурировать типы, вызывать слоты tp_newи tp_initи т. д.

Но,в нем отсутствует важное примечание о передаче аргументов из подтипа в супертип. Судя по примечанию :

(XXX There should be a paragraph or two about argument passing here.)

, PEP -253 не закончен. Итак, я пытаюсь экстраполировать некоторые стратегии , хорошо известные из подтипов классов 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 (или kwdsdict, я предполагаю, что принцип будет таким же ).

Вот некоторый (псевдо-)код, иллюстрирующий ситуацию:

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 , упомянутый выше, и правильную технику передачи аргументов от подтипа до супертипа (s )при построении?

ОБНОВЛЕНИЕ 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.

9
задан Community 23 May 2017 в 11:59
поделиться