我想对此类的inner
列表进行排序。该列表包含名为Edge
的cdef类的对象。 Edge类包含一个名为savings
的成员变量。我想按此变量对列表进行排序。
cdef class Alist:
def __init__(self):
self.inner = []
cdef list inner
cdef void append(self, Edge a):
self.inner.append(a)
cdef void pop(self, int a):
self.inner.pop(a)
cdef void insert(self,int pos,Edge a):
self.inner.insert(pos,a)
cdef int index(self,Edge a):
if a in self.inner:
return self.inner.index(a)
return -1
cdef Edge get(self, int i):
return <Edge> self.inner[i]
cdef void sort(self):
self.inner.sort(key = lambda c : c.Savings)
#self.inner.sort()
def __len__(self):
return len(self.inner)
def __richcmp__(Edge self, Edge other,int op):
if op == 0:
if self.inner.savings < other.inner.savings:
return True
return False
为了做到这一点,我在类中创建了方法sort
,但是当我执行它时,我收到以下错误消息:
例外属性错误:&#34;&#39; fib.Edge&#39;对象没有属性&#39;储蓄&#39;&#34; in&#39; fib.Alist.sort&#39;忽略
答案 0 :(得分:0)
Python-lambda函数无法访问Edge
的cdef属性。如果您尝试从python直接访问cdef类的属性,除非您添加readonly
(用于读取访问)或public
(用于读取和写入访问),否则将收到错误属性定义。
以此Edge类为例:
cdef class Edge:
cdef readonly int savings # visible from python
cdef int foo # not visible from python
def __init__(self, int s):
self.savings = s
self.foo = 42
def __repr__(self):
"""Friendly representation so we can see how the edges sort."""
return "Edge: {}".format(self.savings)
如果我们编译它(假设它驻留在文件sortlist.pyx
中)并将其导入Python shell:
In [1]: import sortlist as sl
In [2]: e = sl.Edge(42)
In [3]: e.savings
Out[3]: 23
In [4]: e.foo
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-4-3ebfe6d526e9> in <module>()
----> 1 e.foo
AttributeError: 'sortlist.Edge' object has no attribute 'foo'
如果您访问readonly
属性saving
,一切正常,但仅Cython属性foo
会引发您获得的错误。并不是属性不存在,Python就是看不到它。
基本上,修复方法是:将readonly
添加到Edge类中的节省声明中。上面的Edge类使用以下代码。
cdef class Alist:
cdef list inner
def __init__(self):
self.inner = []
cdef void append(self, Edge a):
self.inner.append(a)
cdef void sort(self):
self.inner.sort(key = lambda c : c.savings)
def test_sorting():
# create edges with saving between 0 an 9
edges = [Edge(i) for i in range(10)]
# create an intersting instance for sorting
shuffle(edges)
al = Alist()
# fill the inner list
for e in edges:
al.append(e)
print("Finished Alist:", al.inner)
al.sort()
print("Sorted Alist:", al.inner)
在__richcmp__
中定义Alist
方法时,它可用于比较两个Alist
个对象。因此,键入Edge作为此处没有用。
您可以为richcmp
定义Edge
方法,这意味着可以用来比较两个Edge
对象的方法。我强烈建议实施所有比较。因为它现在可能会显示一些奇怪的行为,如
In [1]: e1 = Edge(42)
In [2]: e2 = Edge(42)
In [3]: e3 = Edge(23)
In [4]: e1 < e2
Out[4]: False
# How it is supposed to be
In [5]: e1 == e2
Out[5]: False
# This should be True
In [6]: e1 < e3
Out[6]: True
# How it is supposed to be
In [6]: e1 <= e3
Out[6]: False
# This should be True
因为所有非op=0
的{{1}}操作(也称为<
)的比较默认为False。因此,如果您想使用它,请一直使用。
有关丰富比较的更多详细信息,请参见here。