Не могу вернуть нужный тип данных с помощью Cython - PullRequest
0 голосов
/ 14 ноября 2018

Я хочу построить функцию, которая может возвращать наиболее распространенную перестановку из шести букв «R» плюс шесть букв «B», список может выглядеть так:

a = ['R'] * 6 + ['B'] * 6
random.shuffle(a)
shuffle = ''.join(a)
shuffle

Вывод: 'BRBRRRBBRBBR'

Я хочу написать цикл этой функции, чтобы имитировать наиболее распространенное распределение этих строк. Я написал цикл for с python, и он сработал, но после импорта cython для ускорения этой функции что-то идет не так, вот код:

'''Python Code'''
import random
def random_loop_py(times):
    a = ['R'] * 6 + ['B'] * 6
    count = {}
    for i in range(times):
        random.shuffle(a)
        shuffle = ''.join(a)
        if shuffle in count.keys():
            count[shuffle] += 1
        else:
            count[shuffle] = 1
    return count
%timeit random_loop_py(100000)

'''Cython Code'''
    %load_ext cython
    %%cython
    import random
    cpdef void random_loop(int size):
        a = ['R'] * 6 + ['B'] * 6
        count = {}
        for i in range(size):
            random.shuffle(a)
            shuffle = ''.join(a)
            if shuffle in count.keys():
                count[shuffle] += 1
            else:
                count[shuffle] = 1
        return count.values()

и ошибка:

Error compiling Cython file:
------------------------------------------------------------
...
        shuffle = ''.join(a)
        if shuffle in count.keys():
            count[shuffle] += 1
        else:
            count[shuffle] = 1
    return count.keys()
                    ^
------------------------------------------------------------

/Users/lee_excited/.ipython/cython/_cython_magic_e70ad62499224c5d4fd4e23d6dcb9e49.pyx:12:21: Return with value in void function
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-120-a09f2e5d5e69> in <module>
----> 1 get_ipython().run_cell_magic('cython', '', "import random\ncpdef void random_loop(int size):\n    a = ['R'] * 6 + ['B'] * 6\n    count = {}\n    for i in range(size):\n        random.shuffle(a)\n        shuffle = ''.join(a)\n        if shuffle in count.keys():\n            count[shuffle] += 1\n        else:\n            count[shuffle] = 1\n    return count.keys()\n")

~/anaconda3/lib/python3.6/site-packages/IPython/core/interactiveshell.py in run_cell_magic(self, magic_name, line, cell)
   2321             magic_arg_s = self.var_expand(line, stack_depth)
   2322             with self.builtin_trap:
-> 2323                 result = fn(magic_arg_s, cell)
   2324             return result
   2325 

<decorator-gen-127> in cython(self, line, cell)

~/anaconda3/lib/python3.6/site-packages/IPython/core/magic.py in <lambda>(f, *a, **k)
    185     # but it's overkill for just that one bit of state.
    186     def magic_deco(arg):
--> 187         call = lambda f, *a, **k: f(*a, **k)
    188 
    189         if callable(arg):

~/anaconda3/lib/python3.6/site-packages/Cython/Build/IpythonMagic.py in cython(self, line, cell)
    323         if need_cythonize:
    324             extensions = self._cythonize(module_name, code, lib_dir, args, quiet=args.quiet)
--> 325             assert len(extensions) == 1
    326             extension = extensions[0]
    327             self._code_cache[key] = module_name

TypeError: object of type 'NoneType' has no len()

Какие данные я должен вернуть для ускорения моделирования, пожалуйста?

1 Ответ

0 голосов
/ 14 ноября 2018

Ваша функция имеет тип возвращаемого значения void:

cpdef void random_loop(int size):
    ...
    return count.values()

Следовательно, вы не должны ничего возвращать из него, и сообщение об исключении очень ясно об этом.Измените тип возвращаемого значения на list:

cpdef list random_loop(int size):
    ...
    return list(count.values())

PS

Ваша функция не очень удобна для Cython: я не думаю, что вы получите значительное улучшение производительности.

Обновление

Я не могу воспроизвести вашу ошибку после исправления

In [9]: %%cython
   ...: import random
   ...: cpdef list random_loop(int size):
   ...:     a = ['R'] * 6 + ['B'] * 6
   ...:     count = {}
   ...:     for i in range(size):
   ...:         random.shuffle(a)
   ...:         shuffle = ''.join(a)
   ...:         if shuffle in count.keys():
   ...:             count[shuffle] += 1
   ...:         else:
   ...:             count[shuffle] = 1
   ...:     return list(count.values())
   ...: 

In [10]: random_loop(10)
Out[10]: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1]

Как видите, она прекрасно компилируется.

...