当我遍历相同类型(或派生类)的对象并在循环内调用相同方法时,方法将无法识别。
当我遍历已定义的类中的数据结构(在这种情况下为collections.OrderedDict
)中存储的对象时,会发生这种情况。我已经在pxd
文件中将这些方法提供给Cython。
无论MyClass
是基类还是派生类,都会发生这种情况。
我正在使用unittest
测试我的代码。
我想知道Cython是否不支持此功能,或者在对象扩展为Cython时是否缺少有关该对象的某些信息。
myclass.pxd
cdef class MyClass():
cdef public object _dict
cdef void add_obj(self, name, obj)
cdef void m(self)
cdef void _m(self)
myclass.pyx
from collections import OrderedDict
cdef class MyClass():
def __cinit__(self):
self._dict = OrderedDict()
cdef void add_obj(self, name, obj):
self._dict[name] = obj
cdef void m(self):
# user defines this in derived class
pass
cdef void _m(self):
cdef int i = 0
print('running user defined method')
self.m()
print(self._dict.keys())
print('adding objects')
for key, obj in self._dict.items():
# ERROR
print('obj')
print(obj)
obj.m()
i += 1
print('added an object')
print(i)
test.pyx
from mypkg.core.myclass cimport MyClass
import unittest
cdef class ChildClass(MyClass):
cdef void m(self):
self.add_obj('a', MyClass())
self.add_obj('b', MyClass())
self.add_obj('c', MyClass())
cdef class ParentClass(MyClass):
cdef void m(self):
self.add_obj('a', ChildClass())
self.add_obj('b', ChildClass())
self.add_obj('c', ChildClass())
cdef ParentClass H = ParentClass()
class SetupTree(unittest.TestCase):
def setUp(self):
H._m()
def test_tree(self):
print(H._dict)
print(len(H._dict))
输出
running user defined method
odict_keys(['a', 'b', 'c'])
adding objects
obj
<mypkg.test.test_system2.ChildClass object at 0x7f86ff915b38>
AttributeError: 'mypkg.test.test_system2.ChildClass' object has no attribute 'm'
Exception ignored in: 'mypkg.core.group.MyClass._m'
AttributeError: 'mypkg.test.test_system2.ChildClass' object has no attribute 'm'
OrderedDict([('a', <mypkg.test.test_system2.ChildClass object at 0x7f86ff915b38>), ('b', <mypkg.test.test_system2.ChildClass object at 0x7f86ff915d30>), ('c', <mypkg.test.test_system2.ChildClass object at 0x7f86ff915c88>)])
3
.
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK
答案 0 :(得分:0)
cdef
方法只有在编译时可以找到时才能被调用-在运行时不能将它们视为Python属性。您没有在_m
中做任何事情来告诉Cython obj
是MyClass
,因此它不知道cdef
方法的存在。
您有两个选择:
将cdef m(...)
更改为def
(或cpdef
),以便Python在运行时可以找到它。
告诉Cython obj
是MyClass
的实例:
cdef MyClass obj # you'll receive an TypeError exception if you ever
# attempt to assign something that isn't a MyClass to obj
for key, obj in self._dict.items():
obj.m() # now works!