Da Tupel unveränderlich sind, warum macht das Schneiden sie eine Kopie statt einer Ansicht?

9

Soweit ich es verstehe, sind Tupel und Strings unveränderlich, um Optimierungen wie die Wiederverwendung von Speicher zu ermöglichen, der sich nicht ändert. Eine offensichtliche Optimierung, bei der Tupel-Slices sich auf den gleichen Speicher wie das ursprüngliche Tupel beziehen, ist jedoch in Python nicht enthalten.

Ich weiß, dass diese Optimierung nicht enthalten ist, denn wenn ich die folgende Funktion zeitlich bearbeite, läuft die Zeit wie O (n ^ 2) anstatt O (n), so dass das vollständige Kopieren stattfindet:

%Vor%

Gibt es ein Verhalten von Python, das sich ändern würde, wenn diese Optimierung implementiert wäre? Gibt es einen Leistungsvorteil beim Kopieren, selbst wenn das Original unveränderlich ist?

    
QuadmasterXLII 10.01.2016, 20:38
quelle

1 Antwort

1

Nach view , denken Sie an etwas, das dem von numpy entspricht? Ich weiß, wie und warum numpy das macht.

A numpy array ist ein Objekt mit Form- und Dtypinformationen sowie einem Datenpuffer. Sie können diese Informationen in der __array_interface__ -Eigenschaft sehen. A view ist ein neues numpy-Objekt mit einem eigenen Shape-Attribut, aber mit einem neuen Datenpufferzeiger, der auf eine Stelle im Quellpuffer verweist. Es hat auch eine Flagge, die sagt "Ich besitze nicht den Puffer". numpy behält auch eine eigene Referenzzählung bei, so dass der Datenpuffer nicht zerstört wird, wenn das ursprüngliche (Eigentümer-) Array gelöscht wird (und die Garbage Collection gesammelt wird).

Diese Verwendung von Ansichten kann viel Zeit sparen, besonders bei sehr großen Arrays (Fragen zu Speicherfehlern sind bei SO üblich). Ansichten erlauben auch unterschiedliche dtype , so dass ein Datenpuffer bei 4 Byte Ganzzahlen oder 1 Byte Zeichen usw. angezeigt werden kann.

Wie würde das für Tupel gelten? Meine Vermutung ist, dass es viel zusätzliches Gepäck erfordern würde. Ein Tupel besteht aus einem festen Satz von Objektzeigern - wahrscheinlich einem C-Array. Eine Ansicht würde dasselbe Array verwenden, aber mit eigenen Start- und Endmarkierungen (Zeigern und / oder Längen). Was ist mit Flags teilen? Müllsammlung?

Und was ist die typische Größe und Verwendung von Tupeln? Eine häufige Verwendung von Tupeln besteht darin, Argumente an eine Funktion zu übergeben. Meine Vermutung ist, dass die meisten Tupel in einem typischen Python-Lauf klein sind - 0, 1 oder 2 Elemente. Scheiben sind erlaubt, aber sind sie sehr üblich? Auf kleinen Tupeln oder sehr großen?

Wäre es unbeabsichtigt, Tupel-Slices zu sehen (im angeschlagenen Sinn)? Die Unterscheidung zwischen Ansichten und Kopien ist eine der schwierigsten Aufgaben für numpy . Da ein Tupel unveränderlich sein soll - das heißt, die Zeiger im Tupel können nicht geändert werden - ist es möglich, dass Implementierungsansichten für Benutzer unsichtbar sind. Aber ich frage mich trotzdem.

Es kann am sinnvollsten sein, diese Idee in einem Zweig der PyPy Version zu versuchen - es sei denn, Sie möchten wirklich in Cpython code eintauchen. Oder als benutzerdefinierte Klasse mit Cython .

    
hpaulj 10.01.2016 23:55
quelle

Tags und Links