在cython函数中初始化对象的正确方法



我使用以下密码:

cimport numpy as np
np.import_array()

cdef class Seen:
    cdef bint sint_
    def __cinit__(self):
        print('INIT seen object')
        self.sint_ = 0
    cdef saw_int(self, object val):
        self.sint_ = 1

def test(object val):
    test_type(val)

def test_type(object val, Seen seen=Seen()):
    print ('BEFORE:', seen.sint_)
    val = int(val)
    seen.saw_int(val)
    print ('AFTER:', seen.sint_)

构建它并调用如下函数:

import test
import numpy as np
test.test(-1)
print('')
test.test(np.iinfo(np.uint64).max)

产生问题的输出:

INIT seen object
BEFORE: False
AFTER: True
BEFORE: True
AFTER: True


作为输出状态 - seen对象不会在第二次test.test调用中实例化。但与此同时,如果更改test_type这样的声明:

cdef test_type(object val):
    cdef  Seen seen=Seen()
    ...

初始化发生在每次调用上。

所以2个问题:

  1. 为什么test_type的两种实现是不同的?据我从cython文档中记得,这两者是可以互换的。
  2. 我应该如何将seen对象传递给默认为初始化新对象的test_type?如果 (..., Seen seen=Seen((( 不起作用?

定义函数时,函数的默认值将计算一次。如果每次调用 test_type 时都需要一个新的 Seen 实例,请执行以下操作:

def test_type(object val, Seen seen=None):
    if seen is None:
        seen = Seen()
    print ('BEFORE:', seen.sint_)
    val = int(val)
    seen.saw_int(val)
    print ('AFTER:', seen.sint_)

警告:我对cython不是很熟悉,所以可能缺少一个微妙之处。但这将是普通 Python 代码中的问题,我怀疑同样的问题也适用于这里。

最新更新