[英]Sort a list of cdef objects by attribute in a cdef class
我想對這個類的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
,但是當我執行它時,我獲得以下錯誤消息:
異常AttributeError:''fib.Edge'對象在'fib.Alist.sort'中沒有屬性'Saving'“被忽略
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作為此處沒有用。
您可以做的是為Edge
定義richcmp
方法,這意味着可以用於比較兩個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
比較,即<
operation(也可用作cpython.object.Py_LT
),默認為False。 因此,如果您想使用它,請一直使用。
有關豐富比較的更多詳細信息,請參見此處 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.