2017-05-20 2 views
1

Ich habe eine Klasse, die ein numpy.ndarray als Mitglied hat und verhält sich ähnlich durch ndarray __getitem__ und __getattr__ Überlastung:Python Operatoren für numpy.ndarray wie Klasse

class Foo(object): 
    def __init__(values): 
     # numpy.ndarray 
     self._values = values 

    def __getitem__(self, key): 
     return self._values[key] 

    def __getattr__(self, name): 
     return getattr(self._values, name) 

So kann ich die numpy Methode verwenden, wie Form, Größe, ... direkt auf einem Objekt dieser Klasse. Ich kann auch Dinge wie tun, die 1 zu obj._values hinzufügen wird. Wenn ich jedoch obj + 1 versuche, löst es "nicht unterstützte Operandentyp (e)" aus. Ich möchte das gleiche Verhalten für obj + 1 als erhalten. Ist dies möglich, ohne __add__ zu Foo hinzuzufügen?

+1

Nein, das ist nicht möglich. Sie müssen '__add__' implementieren. – DyZ

+0

Numpy 1.13rc2 hat eine Mixinklasse, die all diese Methoden für Sie implementiert ('numpy.lib.mixins.NDArrayOperatorsMixin') – Eric

Antwort

0

Ich kann sehen, was Sie hier versuchen, aber es wird nicht so funktionieren, wie Sie denken, dass es sollte. Dies ist eine sehr nicht offensichtliche Subtilität in Python.

Was Sie denken, ist das, was Sie obj + 1 Python tatsächlich tun obj.__add__(1) und ruft, in Ermangelung eines __add__ Attribut auf obj zu finden, es durch seine __getattr__ fallen.

Aber das ist nicht so, wie es für arithmetische Operatoren funktioniert, deren Implementierung tatsächlich wesentlich komplizierter ist. In diesem Fall, wenn obj keine __add__ Methode hat, wird versucht, die Methode __radd__ (für "right add") des rechten Operanden aufzurufen, um zu sehen, ob 1 weiß, wie man mit dem linken Operator hinzufügt. Es ist nicht so, dass Sie eine Ausnahme bekommen.

Es gibt andere Feinheiten im Zusammenhang mit Typ-Slots, auf die ich nicht eingehen werde.

Wenn Sie möchten, dass Ihre Klasse als Proxy für eine ndarray fungiert, haben Sie ein paar Optionen. Es hängt wirklich davon ab, was Sie eigentlich erreichen wollen, was Sie vielleicht in einer separaten Frage in Betracht ziehen. Sie können einfach Unterklassendarray direkt und implementieren Sie Ihre zusätzlichen Funktionen in der Unterklasse.

Wenn Sie keine Unterklasse von ndarray möchten, können Sie auch einen Proxy verwenden, z. B. ObjectProxy von wrapt. Dies kann oder kann nicht sein, was Sie wollen. Es macht ein Objekt, das geht, spricht, Quacksalber wie, und sogar ndarray benannt wird, obwohl Sie immer noch ObjectProxy Unterklasse können, um Methoden zu überschreiben, die Sie nicht proxied wollen.

Sonst gibt es die langwierige manuelle Methode.

+0

Danke! Ich möchte nicht wirklich ndarray ableiten, da es nicht-trivial ist und ich bin auch ziemlich glücklich mit der Tatsache, dass ich 'obj [i, j] = 2' nicht tun kann, wenn ich '__setitem__' nicht definiere. Ich werde in Proxy arbeiten oder alles manuell hinzufügen. – Max

+0

FWIW * im Allgemeinen * Unterklassen 'ndarray' ist nicht schwer, aber ich weiß nicht mehr über Ihren Anwendungsfall, den ich nicht sagen könnte. – Iguananaut

Verwandte Themen