Полиморфизм с типами расширения Cython - PullRequest
1 голос
/ 27 мая 2019

У меня есть тип расширения Cython, который я хочу сделать более общим.Одним из атрибутов этого типа расширения является double, и я хочу, чтобы это было представление памяти (double[::1]) при необходимости.

Вот простой пример:

import numpy as np
cimport numpy as np
cimport cython

cdef class Test:

    cdef bint numeric
    cdef double du  

    def __init__(self, bint numeric):

        self.numeric = numeric

        if self.numeric:
            self.du = 1

        else:
            self.du = np.ones(10)

    def disp(self)
        print(self.du)

Test(True).disp()   # returns 1
Test(False).disp()  # gives of course an error

Я попытался создать подкласс Test, изменив тип du на double[::1] и внедрив новый __init__, но, похоже, мы можемпереопределить атрибуты класса типов расширения.Даже если бы это работало, это не было бы удовлетворительно, потому что я действительно не хочу иметь один тип расширения для каждого случая.

Лучше всего, если бы мой тип расширения напрямую обрабатывал оба случая (скаляр du и обзор памяти du).

Есть ли способ сделать это с помощью Cython?

1 Ответ

1 голос
/ 27 мая 2019

К сожалению, вы не можете использовать fused_type в качестве типа атрибута. У вас может быть два варианта:

Вы можете попытаться использовать адрес памяти переменной, которую хотите вызвать, и привести ее при необходимости (все объяснено здесь .) К сожалению, мне не удалось заставить ее работать с типизированной памятью вид.

Или вы можете использовать определенный вами числовой атрибут для вызова соответствующего метода:

import numpy as np
cimport numpy as np
cimport cython

cdef class Test:

    cdef bint numeric
    cdef double du_numeric
    cdef double[:] du_mem_view

    def __init__(self, bint numeric):

        self.numeric = numeric

        if self.numeric:
            self.du_numeric = 1

        else:
            self.du_mem_view = np.ones(10)

    def disp(self):
        if self.numeric:
            print(self.du_numeric)
        else:
            print(self.du_numeric_mem_view)

Test(True).disp()   # returns 1
Test(False).disp()  # Does not give an error anymore !
...