首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >两个Cython函数;为什么一个函数工作,而另一个函数提供NameError?

两个Cython函数;为什么一个函数工作,而另一个函数提供NameError?
EN

Stack Overflow用户
提问于 2020-03-11 16:28:39
回答 1查看 251关注 0票数 0

我正在尝试使用Cython来加速Python脚本的某些部分。其中一个关键部分将函数应用于Pandas dataframe;由于这是多次完成的,因此我希望用Cython编写这些函数,以获得更快的计算速度。功能如下,并在同一个木星笔记本电池:

代码语言:javascript
运行
复制
%%cython
cimport numpy as np
import numpy as np

cdef double breadth_c_type(np.ndarray[np.float64_t, ndim=1] arr):
    """ Calculates range between the maximum and minimum values of a given list. """
    return (max(arr) - min(arr))

cdef double evenness_c_type(np.ndarray[np.float64_t, ndim=1] arr):
    """ Calculates the sample variance of differences between values in a sorted list. """
    cdef np.ndarray[double] sorted_arr
    cdef list desc_diff
    cdef double m
    cdef double var_res
    sorted_arr = sorted(arr)
    desc_diff = []
    for x in range(len(arr)-1):
        desc_diff.append(sorted_arr[x+1]-sorted_arr[x])
    # following used to avoid usage of numpy
    m = sum(desc_diff) / len(desc_diff)
    var_res = sum((xi - m)**2 for xi in desc_diff) / len(desc_diff)
    return var_res

笔记簿单元格以书面方式成功运行,所以我认为这两个函数都编译成功了。但是,此代码按预期运行:

代码语言:javascript
运行
复制
%timeit rand_df.apply(breadth_c_type, raw=True)

鉴于这一守则:

代码语言:javascript
运行
复制
%timeit rand_df.apply(evenness_c_type, raw=True)

不运行,并返回"NameError:名称'evenness_c_type‘未定义“。在没有%timeit修饰符的情况下,我得到了相同的结果,当使用'cpdef‘或'def’代替'cdef‘时,函数不会编译。由于我试图对这两个函数遵循相同的语法,所以我不知道是什么导致了evenness_c_type的错误。

多亏了@DavidW,编辑了,我发现了evenness_c_type()函数的问题。它编译和运行良好,尽管速度不如普通的Cython版本。

代码语言:javascript
运行
复制
cdef double evenness_c_type(np.ndarray[np.float64_t, ndim=1] arr):
    """ Calculates the population variance of differences between values in a sorted list. """
    cdef np.ndarray [double] desc_diff=np.empty(len(arr)-1, dtype = np.float64)
    arr.sort()
    for x in range(len(arr)-1):
        desc_diff[x]=(arr[x+1]-arr[x])
    return np.var(desc_diff)
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-03-11 17:34:47

原则上,两者都不应该使用timeittimeit接受Python,cdef函数不是Python。但是,在某些情况下,Cython将自动创建从cdef函数->Python(实际上使其为cpdef)的转换。

它不使用cpdef编译的原因是生成器表达式("closures inside cpdef functions not yet supported")

代码语言:javascript
运行
复制
var_res = sum((xi - m)**2 for xi in desc_diff) / len(desc_diff)

我收到这样的错误消息,尽管编译器崩溃了,所以它们不是最清楚的。

用一个清单理解来代替它,它会很好(尽管它看起来并不是特别好的优化)

代码语言:javascript
运行
复制
var_res = sum([(xi - m)**2 for xi in desc_diff]) / len(desc_diff)

我怀疑,没有为cdef函数生成自动转换的原因是这个生成器表达式。

它不编译为def函数的原因是您指定了一个返回类型。

考虑一下whether you really need to make it cdef/cpdef。大多数情况下几乎没有什么好处。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60640571

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档