python - Sort a list of cdef objects by attribute in a cdef class -


i sort list inner of class. list contains objects of cdef class called edge. edge class contains member variable called savings. sort list variable.

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 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 

in order that, created method sort inside class, when execute it, obtain following error message:

exception attributeerror: "'fib.edge' object has no attribute 'savings'" in 'fib.alist.sort' ignored

what going wrong here

the python- lambda function can not access cdef attribute of edge. if try directly access attribute of cdef class python error unless add either readonly (for read access) or public (for read , write access) attribute definition.

take edge class example:

cdef class edge:     cdef readonly int savings # visible python     cdef int foo # not visible python      def __init__(self, int s):         self.savings = s         self.foo = 42      def __repr__(self):         """friendly representation can see how edges sort."""         return "edge: {}".format(self.savings) 

if compile (assume resides in file sortlist.pyx) , import in python shell:

in [1]: import sortlist 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' 

if access readonly attribute saving works, cython attribute foo throws error getting. not attribute not there, python can not see it.

working example

basically fix is: add readonly declaration of savings in edge class. edge class above works following code.

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 saving between 0 9     edges = [edge(i) in range(10)]     # create intersting instance sorting     shuffle(edges)     al = alist()     # fill inner list     e in edges:         al.append(e)     print("finished alist:", al.inner)     al.sort()     print("sorted alist:", al.inner) 

why might not need richcmp (where now)

when define __richcmp__ method in alist can used compare 2 alist objects. hence typing edge not useful here.

what define richcmp method edge, meaning method can used compare 2 edge objects. advise implement all comparisons then. because might show weird behavior like

in [1]: e1 = edge(42)  in [2]: e2 = edge(42)  in [3]: e3 = edge(23)  in [4]: e1 < e2 out[4]: false # how supposed  in [5]: e1 == e2 out[5]: false  # should true  in [6]: e1 < e3 out[6]: true # how supposed  in [6]: e1 <= e3 out[6]: false # should true 

because comparisons not op=0 < operation (also available cpython.object.py_lt) default false. if want use this, go way.

more details on rich comparison can found here.


Popular posts from this blog

php - How should I create my API for mobile applications (Needs Authentication) -

5 Reasons to Blog Anonymously (and 5 Reasons Not To)

Google AdWords and AdSense - A Dynamic Small Business Marketing Duo