Cython не может использовать setattr

У меня есть класс cdef в Cython, и я хочу инициализировать его поля с помощью встроенной функции setattr. Однако, когда я делаю это, я получаю ошибку выполнения:

/path/.../cimul.cpython-34m.so in cimul.Simulation.__init__ (cimul.c:5100)()
AttributeError: 'Simulation' object has no attribute 'Re'

Мой код выглядит следующим образом:

cdef class Simulation:
    cdef double Re, Pr, Ra, a, dt_security
    cdef int Nz, NFourier, freq_output, freq_critical_Ra, maxiter
    cdef bool verbose

    def __init__(self, *args, **kargs):
        param_list = {'Re': 1, 'Pr': 1, 'Ra': 1, 'a' : 1, 'Nz': 100,
                      'NFourier': 50, 'dt_security': 0.9,
                      'maxiter': 100, 'freq_output': 10,
                      'freq_critical_Ra':50, 'verbose': False}
        # save the default parameters
        for param, value in param_list.items():
            setattr(self, param, value)

Ты хоть представляешь, как я могу обойти эту проблему?

1 ответ

  • Когда вы определяете атрибут cdefining (без public) в классе, вы действительно определяете какое-то поле в C-структуре. Поэтому после компиляции (Cython + C) имя атрибута теряется, они идентифицируются только по некоторому смещению от начала структуры C. Как следствие, они не доступны из Python.

  • Если вы добавите cdef publicCython добавляет некоторую функцию доступа к свойству, которая не только разрешает доступ из Python, но также сохраняет смещение идентификатора ассоциации <-> в структуре C. С этими функциями свойств связаны небольшие издержки. Также обратите внимание, что эти функции выполняют проверку / преобразование типа Python -> C.

Теперь, чтобы ответить на ваш вопрос, вам нужно как-то сохранить смещение идентификатора ассоциации <->. Если вы хотите, чтобы все было быстро, единственный способ сделать это вручную:

self.RE = param_list['RE']   # self.RE is a C struct access
self.Pr = param_list['Pr']
...
Другие вопросы по тегам