Übergeben einer Zython-Funktion vs eine Cython-Methode zu scipy.integrate

Ich versuche zu arbeiten, wie man Cython benutzt, um eine Berechnung zu beschleunigen, die eine Integration beinhaltet, die innerhalb einer Klasse erfolgt, die ich definiert habe. Ich versuche, besser zu verstehen, wie Cython mit benutzerdefinierten Python-Klassen arbeitet. Ich würde gerne mehr darüber erfahren, warum der unten beschriebene Fehler auftritt.

Ich habe den folgenden Zython-Code in einer Datei namens ex.pyx

 from libc.math cimport log from libc.math cimport sqrt import scipy.integrate as integ cdef double integrand_outside(double x): """Cython: integrand outside the class""" cdef double f = log(x) / sqrt(x) return f cdef class CalcSomething(object): def integrate_other(self, double a, double b): """This does the integral with the integrand outside the class""" return integ.quad(integrand_outside, a, b)[0] def integrate_self(self, double a, double b): """This does the integral with the integrand inside the class""" return integ.quad(self._integrand, a, b)[0] def integrate_wrap_self(self, double a, double b): """This does the integral with the integrand inside the class""" return integ.quad(self.wrap_integrand, a, b)[0] def wrap_integrand(self, double x): """Python method that wraps _integrand""" return self._integrand(x) cdef double _integrand(self, double x): """Cython: integrand inside the class""" cdef double f = log(x) / sqrt(x) return f 

Es zeigt drei Möglichkeiten, scipy.integrate.quad aus einer Klasse zu nennen

  1. Mit einer außerhalb der Klasse definierten Cython-Integrand-Funktion: integrate_other (ok!)
  2. Mit einer in der Klasse definierten Cython-Integrand-Funktion: integrate_self (erzeugt Fehler)
  3. Wrapping der Cython-Integrand-Funktion innerhalb der Klasse in einer Python-Funktion definiert innerhalb der Klasse definiert: integrate_wrap_self (ok!)

Der obige Zython-Code kompiliert gut. Jetzt rufe ich jede dieser integrierten Methoden an, zB

 import ex calcSomething = ex.CalcSomething() a = 0.001 b = 0.1 calcSomething.integrate_other(a,b) # works calcSomething.integrate_wrap_self(a,b) # works calcSomething.integrate_self(a,b) # doesn't work 

Hier ist die Rückverfolgung:

 Traceback (most recent call last): File "../examples/example.py", line 10, in <module> print "integrate self =", calcSomething.integrate_self(a,b) # doesn't work File "ex.pyx", line 17, in ex.CalcSomething.integrate_self (ex.c:989) return integ.quad(self._integrand, a, b)[0] File "/home/alex/Enthought/Canopy_64bit/User/lib/python2.7/site-packages/scipy/integrate/quadpack.py", line 281, in quad retval = _quad(func,a,b,args,full_output,epsabs,epsrel,limit,points) File "/home/alex/Enthought/Canopy_64bit/User/lib/python2.7/site-packages/scipy/integrate/quadpack.py", line 345, in _quad return _quadpack._qagse(func,a,b,args,full_output,epsabs,epsrel,limit) File "stringsource", line 30, in cfunc.to_py.__Pyx_CFunc_double____CalcSomething____double___to_py.wrap (ex.c:1560) TypeError: wrap() takes exactly 2 positional arguments (1 given) 

Hier sind meine Fragen:

  • Warum kann scipy.integrate als Cython-Funktion oder eine Python-Methode übergeben werden (also jetzt mit Instanz als erstes Argument), aber nicht als Cython-Methode? Der Fehler: TypeError: wrap() takes exactly 2 positional arguments (1 given) impliziert das Problem ist mit dem Instanz-Argument, das mit der Cython-Methode übergeben wird, denke ich?

  • Ist dieser Irrtum aus meinem Missverständnis, wie man Zython macht, oder eine Beschränkung von scipy ?

  • Ist mein beabsichtigter Plan, ein Integral innerhalb einer Klasse zu berechnen (indem ich eine Integrandfunktion auch innerhalb der Klasse anrufe) eine schlechte Lösung, wenn ich über Cython beschleunigen möchte? Disclosure: Der reale Code ruft GSL-Integrationsfunktionen auf, nicht scipy .

  • Wähle eine Unterklasse auf Basis eines Parameters
  • Am besten geeigneten Weg, um Features einer Klasse zu einem anderen zu kombinieren?
  • Wie implementiere ich Schnittstellen in Python?
  • Pandas DataFrame Object Vererbung oder Objekt verwenden?
  • Wie kann ich die Basis- (Super-) Klasse initialisieren?
  • Schlechtes Üben, um Code im Konstruktor zu führen, der wahrscheinlich fehlschlägt?
  • One Solution collect form web for “Übergeben einer Zython-Funktion vs eine Cython-Methode zu scipy.integrate”

    Von hpaulj's Hilfe oben: die Antwort ist die _integrand Methode muss deklariert werden cpdef nicht cdef

     cpdef double _integrand(self, double x): """Cython: integrand inside the class""" cdef double f = log(x) / sqrt(x) return f 
    Python ist die beste Programmiersprache der Welt.