【问题标题】:Can't return wanting type of data using Cython无法使用 Cython 返回所需类型的数据
【发布时间】:2018-11-14 12:36:35
【问题描述】:

我想构建一个函数,可以返回六个“R”字母加六个“B”字母的最常见排列,列表可能如下所示:

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

输出:'BRBRRRBBRBBR'

我想写一个这个函数的循环来模拟这些字符串最常见的分布。我确实用python写了一个for循环,它确实有效,但是在我导入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()

请问我应该返回什么样的数据来加速我的模拟?

【问题讨论】:

  • 请以文本形式发布您的代码和异常。
  • 好的,我已经添加了代码。
  • 完全删除屏幕截图。包括输出。
  • 好的,删除并重新安排问题结构。
  • 好的,删除并重新安排问题结构。 @MadPhysicist

标签: python cython cythonize


【解决方案1】:

你的函数有一个void 返回类型:

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

因此,您不应该从中返回任何内容,并且异常消息对此非常清楚。将返回类型更改为list

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

附言

您的函数对 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]

如您所见,它编译得非常好。

【讨论】:

  • 试过了,还是报错/(ㄒoㄒ)/~~
  • @WeizheLi 你应该澄清这是同一个错误还是一个新错误
  • 其实我试过 print(count.values()) 并且它可以工作,大约加速了 10 倍,所以我试图直接返回 dict,但是出了点问题。伤心。
  • @WeizheLi 我无​​法重现您的错误。查看更新
  • 也许是因为我的 IDLE 是 Jupyter ?
猜你喜欢
  • 2021-07-02
  • 1970-01-01
  • 2015-01-21
  • 2013-04-18
  • 2012-11-25
  • 1970-01-01
  • 1970-01-01
  • 2018-11-14
  • 1970-01-01
相关资源
最近更新 更多