Ich schreibe einen AI-Zustandsraumsuchalgorithmus und habe eine generische Klasse, mit der ein Suchalgorithmus schnell implementiert werden kann. Eine Unterklasse würde die notwendigen Operationen definieren, und der Algorithmus erledigt den Rest.
Hier stecke ich fest: Ich möchte vermeiden, den übergeordneten Status immer wieder neu zu generieren, daher habe ich die folgende Funktion, die die Operationen zurückgibt, die legal auf jeden Status angewendet werden können:
def get_operations(self, include_parent=True):
ops = self._get_operations()
if not include_parent and self.path.parent_op:
try:
parent_inverse = self.invert_op(self.path.parent_op)
ops.remove(parent_inverse)
except NotImplementedError:
pass
return ops
Und die Funktion invert_op wird standardmäßig ausgelöst.
Gibt es eine schnellere Möglichkeit, um zu überprüfen, ob die Funktion nicht definiert ist, als eine Ausnahme abzufangen?
Ich habe etwas überlegt, ob ich in dir nach der Gegenwart suchen soll, aber das scheint nicht richtig zu sein. hasattr wird implementiert, indem getattr aufgerufen und überprüft wird, ob es ausgelöst wird, was ich nicht möchte.
has_op = lambda obj, op: callable(getattr(obj, op, None))
hasattr(connection, 'invert_opt')
.Antworten:
Ja, verwenden Sie diese Option,
getattr()
um das Attributcallable()
abzurufen und zu überprüfen, ob es sich um eine Methode handelt:Beachten Sie, dass
getattr()
normalerweise eine Ausnahme ausgelöst wird, wenn das Attribut nicht vorhanden ist. Wenn Sie jedoch einen Standardwert angeben (None
in diesem Fall), wird dieser stattdessen zurückgegeben.quelle
getattr
in diesem Fall eine Ausnahme stillschweigend abfängt und stattdessen den Standardwert zurückgibt, genau wie dies derhasattr
Fall ist, gegen den das OP aus irgendeinem Grund war.Es funktioniert sowohl in Python 2 als auch in Python 3
hasattr
Gibt zurück,True
wenn für das Verbindungsobjekt eine Funktioninvert_opt
definiert ist. Hier ist die Dokumentation, auf der Sie grasen könnenhttps://docs.python.org/2/library/functions.html#hasattr https://docs.python.org/3/library/functions.html#hasattr
quelle
connection.invert_opt = 'foo'
.Warum bist du dagegen? In den meisten pythonischen Fällen ist es besser, um Vergebung als um Erlaubnis zu bitten. ;-);
Warum ist das so? Das Folgende ist ziemlich pythonisch:
Oder,
Beachten Sie jedoch, dass dies
getattr(obj, attr, default)
im Wesentlichen auch durch das Abfangen einer Ausnahme implementiert wird. Daran ist im Python-Land nichts auszusetzen!quelle
Die Antworten hier prüfen, ob eine Zeichenfolge der Name eines Attributs des Objekts ist. Ein zusätzlicher Schritt (unter Verwendung von callable) ist erforderlich, um zu überprüfen, ob das Attribut eine Methode ist.
Es läuft also darauf hinaus: Was ist der schnellste Weg, um zu überprüfen, ob ein Objekt obj ein Attribut Attribut hat. Die Antwort ist
Dies liegt daran, dass ein Diktat seine Schlüssel hasht, sodass die Überprüfung der Existenz des Schlüssels schnell erfolgt.
Siehe Timing-Vergleiche unten.
quelle
__slots__
.__slots__
Beschleunigen Sie den Zugriff auf Attribute um ~ 10%. stackoverflow.com/a/14119024/1459669Ich mag die Antwort von Nathan Ostgard und habe sie hochgestimmt. Eine andere Möglichkeit, Ihr Problem zu lösen, besteht darin, einen Erinnerungsdekorator zu verwenden, der das Ergebnis des Funktionsaufrufs zwischenspeichert. Sie können also eine teure Funktion haben, die etwas herausfindet, aber wenn Sie sie immer wieder aufrufen, sind die nachfolgenden Anrufe schnell. Die gespeicherte Version der Funktion sucht nach den Argumenten in einem Diktat, findet das Ergebnis im Diktat ab dem Zeitpunkt, an dem die eigentliche Funktion das Ergebnis berechnet hat, und gibt das Ergebnis sofort zurück.
Hier ist ein Rezept für einen Erinnerungsdekorateur namens "lru_cache" von Raymond Hettinger. Eine Version davon ist jetzt Standard im functools-Modul in Python 3.2.
http://code.activestate.com/recipes/498245-lru-and-lfu-cache-decorators/
http://docs.python.org/release/3.2/library/functools.html
quelle
Wie alles in Python können Sie, wenn Sie sich genug anstrengen, den Mut aufbringen und etwas wirklich Böses tun. Hier ist der böse Teil:
Bitte tun Sie uns einen Gefallen, tun Sie einfach weiter, was Sie in Ihrer Frage haben, und verwenden Sie dies NICHT , es sei denn, Sie sind im PyPy-Team und hacken sich in den Python-Interpreter. Was du da oben hast, ist Pythonic, was ich hier habe, ist reines BÖSE .
quelle
co_names
gleich ist('NotImplementedError',)
. Ich bin mir jedoch nicht sicher, ob dies mehr oder weniger böse ist.Sie können auch die Klasse durchgehen:
quelle
Die Suche nach Attributen in der Eigenschaft __dict__ ist zwar sehr schnell, Sie können dies jedoch nicht für Methoden verwenden, da sie nicht im Hash __dict__ angezeigt werden. Sie können jedoch auf eine hackige Problemumgehung in Ihrer Klasse zurückgreifen, wenn die Leistung so kritisch ist:
Überprüfen Sie dann die Methode wie folgt:
Zeitvergleich mit
getattr
:Nicht, dass ich diesen Ansatz ermutige, aber er scheint zu funktionieren.
[EDIT] Die Leistungssteigerung ist noch höher, wenn der Methodenname nicht in der angegebenen Klasse enthalten ist:
quelle
__dict__
könnte überschrieben werden. Es kann nicht vertraut werden.