2012-06-07 2 views
3

Существует ли стандартизованный (или общепринятый способ) решение проблемы невозможности перегрузки __cinit__ методов в cython при обертке классов C++?Cython и перегруженные конструкторы C++

Существует возможность сделать __cinit__ принимать * args и ** kwargs для добавления параметров, а внутри области __cinit__ выбрать способ генерации экземпляра C++ в соответствии с определенным шаблоном. Такой подход, однако, имеет осложнение:

  • Попытки определить правильный конструктор из аргументов может быть опасными при определенных обстоятельствах, если аргументы не будут названы и передаются как kwargs, которые могли бы стать обременительными для пользователей.
  • Когда аргументы не вызываются их типом в списке аргументов __cinit__, они передаются как объекты Python. В моем рабочем случае аргументами являются оболочки Python для классов C++, и попытка получить эти экземпляры «thisptr» является задачей дьявола, когда они передаются как объекты Python из * args или ** kwargs.
  • Предполагаемая необходимость использования последовательности if ... elif ... else для выбора конструктора C++ из комбинации аргументов в конечном итоге становится довольно запутанной.

Так что должен быть лучший способ. Одним из способов может быть использование подхода classmethod (например, см.: classmethod to overload __init__ behavior in Python). Тем не менее, насколько я знаю (и, пожалуйста, поправьте меня, если я ошибаюсь), classmethod подразумевает использование методов с именами, отличными от имени класса, и это не похоже на C++ способ построения экземпляров только с одним именем класса.

Любые идеи по этому вопросу?

ответ

2

Лично я хотел бы использовать classmethods.

WrapperClass.fromSpambar(spambar) 

Это не то, что puzzlin имхо. Если вы не сможете перегружать функции на C++, вам также необходимо отступить от этого подхода.

Если вы можете принять некоторые тяжелые взвешенные операции при инициализации, вы можете реализовать метод распознавания способа создания конструктора путем определения «шаблонов» или аналогичных. То есть Регулярные выражения для args и kwargs. ;)

Я не вижу проблемы с получением thisptr с объекта Python.

cdef WrapperClass wrpclsi 
if isinstance(instance, WrapperClass): 
    wrpclsi = instance 
else: 
    raise TypeError('expected instance of WrapperClass.') 

cdef WrappedClassFromCpp* thisptr = wrpclsi.thisptr 
+0

Большое спасибо Niklas, да, похоже, что для этого нужно использовать методы класса, что также сделает более безопасным обработку определенных комбинаций типов аргументов. Regex, вероятно, будет полезен в сочетании с classmethods (например, выбирая конкретный конструктор classmethod с учетом комбинации типов аргументов, если это имеет смысл). –

+0

Что касается части thisptr ... да, я думаю, что эта точка нуждается в некоторой ясности в отношении того, что я хотел сказать. Я хотел сказать, что объявление 'def __cinit __ (self, PyKlass klass)' не будет проблем с вызовом 'klass.thisptr' внутри области' __cinit__'. Однако, объявив: 'def __cinit (self, * args)' Предполагая, что в args [0] имеется экземпляр PyKlass, вызывающий 'args [0] .thisptr' даст проблемы, даже если args [0] экземпляр типа PyClass. Получается, что это не имеет большого значения, и его можно обойти, просто введя в '__cinit__', например: ' klass = args [0] ' –

+0

Привет тахи. Я фактически не говорил о реальных регулярных выражениях, просто что-то, что работает с сопоставимым механизмом, но сопоставляя * args * и * kwargs *. Точно так же функция отображает переданные аргументы в аргументы, которые она принимает, вы можете обрабатывать * args * и * kwargs *, но допускать множественные соглашения о вызовах. Однако это потребует обработки, которая может значительно замедлить работу. На следующий день я могу написать код примера. –

Смежные вопросы