Невозможно вернуть желаемый тип данных с помощью Cython

Я хочу создать функцию, которая может возвращать наиболее распространенную перестановку шести букв «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()

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


person Weizhe Li    schedule 14.11.2018    source источник
comment
Пожалуйста, опубликуйте свой код и исключения в виде текста.   -  person Eli Korvigo    schedule 14.11.2018
comment
Хорошо, я добавил код.   -  person Weizhe Li    schedule 14.11.2018
comment
Полностью уберите скриншоты. В том числе на выходе.   -  person Mad Physicist    schedule 14.11.2018
comment
Хорошо, удалил и переставил структуру задачи.   -  person Weizhe Li    schedule 14.11.2018
comment
Хорошо, удалил и переставил структуру задачи. @MadPhysicist   -  person Weizhe Li    schedule 14.11.2018
comment
Просто для ясности: вы делаете это, чтобы найти неоднородности в том, как работает random.shuffle?   -  person Mad Physicist    schedule 14.11.2018


Ответы (1)


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

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

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

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

P.S.

Ваша функция не очень удобна для 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]

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

person Eli Korvigo    schedule 14.11.2018
comment
Пробовал, все равно ошибка /(ㄒoㄒ)/~~ - person Weizhe Li; 14.11.2018
comment
@WeizheLi Вы должны уточнить, является ли это той же ошибкой или новой. - person Eli Korvigo; 14.11.2018
comment
На самом деле я попробовал print(count.values()) и это работает, ускорение примерно в 10 раз, поэтому я попытался напрямую вернуть dict, но что-то пошло не так. грустный. - person Weizhe Li; 14.11.2018
comment
@WeizheLi Я не могу воспроизвести вашу ошибку. Посмотреть обновление - person Eli Korvigo; 14.11.2018
comment
Может потому что мой IDLE это Jupyter ???? - person Weizhe Li; 14.11.2018
comment
@WeizheLi Jupyter ничем не отличается от iPython (который я здесь использую). - person Eli Korvigo; 14.11.2018
comment
Странно, позволь мне скопировать твое. - person Weizhe Li; 14.11.2018
comment
Все еще не работает, могу я спросить, какую версию Python и Cython вы используете? - person Weizhe Li; 14.11.2018
comment
Мой: Python 3.6.6 final 0, Cython 0.29 - person Weizhe Li; 14.11.2018
comment
@WeizheLi Python 3.6.5, Cython 0.28.2. Не должно быть никакой разницы. Вы действительно копируете мой код из блока Update? - person Eli Korvigo; 14.11.2018
comment
Работал, тот же код, другой вывод, путаница. Но большое спасибо. XD - person Weizhe Li; 14.11.2018
comment
Да, миллионы благодарностей. И, как вы сказали, он не получает значительных улучшений производительности, в отличие от функции печати. Но я не знаю почему из-за моего плохого навыка кодирования???? - person Weizhe Li; 14.11.2018
comment
@WeizheLi, вы можете принять ответ, если он решил вашу проблему. - person Eli Korvigo; 14.11.2018