2017-11-27 32 views
1

Dies ist eine Frage zu Sage, die auf Python 2.7 basiert. Ich habe die weise Frage here geschrieben, aber diese Frage ändern, um den mathematischen Kontext zu entfernen."Ersetzen" bestimmte Funktionsaufrufe

Ich versuche, die Geschwindigkeit einiger langsamer Funktionen für sehr spezifische Fälle zu verbessern. Im Wesentlichen habe ich eine Funktion foo, so dass foo(args) ist traditionell ziemlich langsam, aber aber aufgrund der Analyse habe ich von Hand, foo(args') kann einfach über bar(args') berechnet werden (für spezielle Fälle von args', die in der Praxis einfach zu überprüfen sind) . Ich möchte eine neue Version von foo so haben, dass:

  1. Wenn args == args' (oder args in A, wo A einige Datenstruktur, die alle Eingaben enthält bar für richtig ist) es nennt nur bar(args)
  2. Andernfalls , ruft foo(args)

Nun, wenn foo nur in meinem eigenen Code definiert wurden, wäre dies trivial zu beheben (durch die Definition ändern oder potenziell einen Dekorateur).

Mein Problem ist, dass foo in module1 ist (nicht mein Code). module2 importiert auch foo, und ich möchte diese Änderung für alles in module2 ebenso sichtbar sein (im Wesentlichen, ich selbst nie foo aufrufen, so für die Beschleunigung auftreten ich brauche andere Funktionen, um den spezifischen Fall schneller zu berechnen).

Ich habe meinen eigenen Code, der module1 und module2 importiert. Gibt es eine Möglichkeit, foo (von innerhalb meines eigenen Codes) zu modifizieren, um diesen Sonderfall schneller zu behandeln, so dass, wenn Funktionen in module1 und module2 es nennen, sie auch die Beschleunigung bekommen? Dies ist nur dann nützlich, wenn es möglich ist, den Quellcode von module1 und module2 zu ändern.

EDIT

In Anbetracht der Antwort unten, gibt es Möglichkeiten, um Affen-Patch-Anrufe zu PARI in Sage? Die Methode, die ich versuche zu monkey-patch, wird vom Profiler als {method '_nf_rnfeq' of 'sage.libs.cypari2.gen.gen' objects} beschrieben. Vor diesem Hintergrund habe ich Folgendes versucht, was nicht funktioniert hat.

import sage.libs.cypari2.gen 
orig_nf_rnfeq = sage.libs.cypari2.gen.gen._nf_rnfeq 
def _nf_rnfeq(*args, **kwargs): 
    print("Rnfeq works!") 
    return orig_nf_rnfeq(*args, **kwargs) 

sage.libs.cypari2.gen.gen._nf_rnfeq = _nf_rnfeq 

Dies führt zu dem Fehler TypeError: can't set attributes of built-in/extension type 'sage.libs.cypari2.gen.gen

Antwort

1
import module1 
origfoo = module1.foo 

def myfoo(*args): 
    if args in A: 
     return bar(*args) 
    return origfoo(*args) 

module1.foo = myfoo 

Jedes Modul, das module1 nach diesem Punkt importiert wird Ihre modifizierte Version der Funktion aufheben. Sie könnten ein Problem haben, wenn module1 selbst module2 importiert, bevor Sie eine Chance haben, den Patch anzuwenden.

+0

Bei dem Versuch, dies zu implementieren, erhalte ich den folgenden Fehler: 'TypeError: Attribute des integrierten/Erweiterungstyps 'sage.libs.cypari2.gen.gen'' können nicht festgelegt werden. Es scheint mit dem Problem [hier] verwandt zu sein (https://stackoverflow.com/questions/192649/can-you-monkey-patch-methods-on-core-types-in-python), also werde ich versuchen, es zu untersuchen Das. – Mark