Was ist der richtige (oder beste) Weg, um die Python-Set-Klasse unterzuordnen und eine neue Instanzvariable hinzuzufügen?

8

Ich implementiere ein Objekt, das fast identisch mit einer Menge ist, aber eine zusätzliche Instanzvariable benötigt, daher unterteile ich das eingebaute Mengenobjekt. Was ist der beste Weg, um sicherzustellen, dass der Wert dieser Variablen kopiert wird, wenn eines meiner Objekte kopiert wird?

Unter Verwendung des alten Sets-Moduls funktionierte der folgende Code perfekt:

%Vor%

Dies funktioniert jedoch nicht mit dem integrierten Set-Modul.

Die einzige Lösung, die ich sehen kann, besteht darin, jede einzelne Methode zu überschreiben, die ein kopiertes Set-Objekt zurückgibt ... in diesem Fall könnte ich das Set-Objekt nicht als Unterklasse betrachten. Sicherlich gibt es einen Standard Weg, dies zu tun?

(Um zu verdeutlichen, dass der folgende Code nicht funktioniert (die Assertion schlägt fehl):

%Vor%

)

    
rog 28.04.2009, 15:05
quelle

7 Antworten

14

Meine bevorzugte Methode zum Einschließen von Methoden einer integrierten Sammlung:

%Vor%

Im Wesentlichen dasselbe, was Sie in Ihrer eigenen Antwort tun, aber mit weniger loc. Es ist auch einfach, eine Metaklasse zu erstellen, wenn Sie dasselbe mit Listen und Dikts machen möchten.

    
Matthew Marshall 30.04.2009, 01:01
quelle
4
___ qstnhdr ___ Was ist der richtige (oder beste) Weg, um die Python-Set-Klasse unterzuordnen und eine neue Instanzvariable hinzuzufügen? ___ antwort6698723 ___

Ich denke, der empfohlene Weg, dies zu tun, besteht nicht darin, direkt von der eingebauten set abzurücken, sondern die Abstrakte Basisklasse Set verfügbar in Sammlungen .

Wenn Sie das ABC-Set verwenden, erhalten Sie einige Methoden kostenlos als Mix-In, so dass Sie eine minimale Set-Klasse haben können, indem Sie nur __contains__() , __len__() und __iter__() definieren. Wenn Sie einige der schöneren Methoden wie intersection() und difference() möchten, müssen Sie sie wahrscheinlich umbrechen.

Hier ist mein Versuch (dieser ist zufällig ein "frozenset-like", aber Sie können von MutableSet erben, um eine veränderbare Version zu erhalten):

%Vor%     
___ qstntxt ___

Ich implementiere ein Objekt, das fast identisch mit einer Menge ist, aber eine zusätzliche Instanzvariable benötigt, daher unterteile ich das eingebaute Mengenobjekt. Was ist der beste Weg, um sicherzustellen, dass der Wert dieser Variablen kopiert wird, wenn eines meiner Objekte kopiert wird?

Unter Verwendung des alten Sets-Moduls funktionierte der folgende Code perfekt:

%Vor%

Dies funktioniert jedoch nicht mit dem integrierten Set-Modul.

Die einzige Lösung, die ich sehen kann, besteht darin, jede einzelne Methode zu überschreiben, die ein kopiertes Set-Objekt zurückgibt ... in diesem Fall könnte ich das Set-Objekt nicht als Unterklasse betrachten. Sicherlich gibt es einen Standard Weg, dies zu tun?

(Um zu verdeutlichen, dass der folgende Code nicht funktioniert (die Assertion schlägt fehl):

%Vor%

)

    
___ answer798548 ___

%code% ist eine Operation, die keine der vorhandenen %code% ändert, sondern stattdessen eine neue %code% zurückgibt. Der neue %code% wird erstellt und zurückgegeben. Es gibt keine Möglichkeit, die arbrity -Attribute automatisch von einem oder beiden %code% s in den neu erstellten %code% zu kopieren, ohne den Operator %code% selbst durch Definieren der Methode %code% .

%Vor%

Drucke:

%Vor%     
___ answer804973 ___

Meine bevorzugte Methode zum Einschließen von Methoden einer integrierten Sammlung:

%Vor%

Im Wesentlichen dasselbe, was Sie in Ihrer eigenen Antwort tun, aber mit weniger loc. Es ist auch einfach, eine Metaklasse zu erstellen, wenn Sie dasselbe mit Listen und Dikts machen möchten.

    
___ answer798595 ___

Für mich funktioniert das perfekt mit Python 2.5.2 auf Win32. Verwenden Sie Ihre Klassendefinition und den folgenden Test:

%Vor%

Ich bekomme diese Ausgabe, was ich erwarte:

%Vor%     
___ answer798676 ___

Es sieht so aus, als setze% um_de% im c-Code . Wie auch immer, Sie werden eine Instanz von %code% beenden, es wird keine Chance geben das Feld zu kopieren.

Abgesehen davon, dass ich die Methoden, die neue Sätze zurückgeben, außer Kraft gesetzt habe, bin ich mir nicht sicher, ob Sie in diesem Fall zu viel tun können. Set ist klar für eine gewisse Geschwindigkeit gebaut, so macht eine Menge Arbeit in c.

    
___ answer12319510 ___

Bedauerlicherweise folgt set nicht den Regeln und %code% wird nicht aufgerufen, um neue %code% -Objekte zu erstellen, obwohl sie den Typ behalten. Dies ist eindeutig ein Fehler in Python (Problem # 1721812, der in der 2.x-Sequenz nicht behoben wird). Sie sollten niemals ein Objekt vom Typ X erhalten, ohne das Objekt %code% aufzurufen, das X-Objekte erzeugt! Wenn %code% nicht %code% aufruft, ist es formal verpflichtet, %code% -Objekte anstelle von Unterklassenobjekten zurückzugeben.

Aber wenn Sie den Post mit nosklo oben notieren, macht Ihr ursprüngliches Verhalten keinen Sinn. Der %code% -Operator sollte keines der Quellobjekte wieder verwenden, um sein Ergebnis zu konstruieren, sondern sollte einen neuen erstellen, in diesem Fall sollte %code% %code% !

sein

Praktisch sollte jeder, der macht diese Operatoren überladen, damit er weiß, welche Kopie von %code% verwendet wird. Wenn es nicht davon abhängig ist, dass die Foosets kombiniert werden, können Sie es als Klassenstandard festlegen. In diesem Fall wird es berücksichtigt, da das neue Objekt denkt, dass es vom Unterklasse-Typ ist.

Was ich meine, ist, dass Ihr Beispiel irgendwie funktionieren würde, wenn Sie das getan hätten:

%Vor%     
___ answer798794 ___

Unter der Annahme, dass die anderen Antworten korrekt sind, und das Überschreiben aller Methoden die einzige Möglichkeit ist, dies zu tun, hier ist mein Versuch einer mäßig eleganten Art, dies zu tun. Wenn mehrere Instanzvariablen hinzugefügt werden, muss nur ein Code geändert werden. Wenn ein neuer binärer Operator zum Set-Objekt hinzugefügt wird, wird dieser Code leider nicht funktionieren, aber ich glaube nicht, dass es einen Weg gibt, dies zu vermeiden. Kommentare willkommen!

%Vor%     
___ tag123set ___ Eine Menge ist eine Sammlung, in der kein Element wiederholt wird, die ihre Elemente möglicherweise nach einem Ordnungskriterium (einer "geordneten Menge") auflisten oder keine Reihenfolge beibehalten kann (eine "ungeordnete Menge"). ___ tag123subclass ___ Eine Unterklasse ist eine Klasse, die von einer übergeordneten (oder übergeordneten) Klasse abgeleitet oder erbt. Subclassing wird häufig in der objektorientierten Programmierung (OOP) verwendet. ___ tag123python ___ Python ist eine dynamische und stark typisierte Programmiersprache, die die Usability betont. Zwei ähnliche, aber größtenteils inkompatible Versionen von Python sind weit verbreitet (2 und 3). Wenn Sie eine versionsspezifische Python-Frage haben, sollten Sie die Tags [python-2.7] oder [python-3.x] zusätzlich zum Tag [python] verwenden. Wenn Sie eine Python-Variante wie jython, pypy, iron-python usw. verwenden, kennzeichnen Sie diese bitte entsprechend. ___ tag123instancevariables ___ Bei der objektorientierten Programmierung mit Klassen ist eine Instanzvariable eine Variable, die in einer Klasse definiert ist (d. h. eine Membervariable), für die jedes Objekt der Klasse eine separate Kopie hat. ___
bjmc 14.07.2011 19:15
quelle
3

Bedauerlicherweise folgt set nicht den Regeln und __new__ wird nicht aufgerufen, um neue set -Objekte zu erstellen, obwohl sie den Typ behalten. Dies ist eindeutig ein Fehler in Python (Problem # 1721812, der in der 2.x-Sequenz nicht behoben wird). Sie sollten niemals ein Objekt vom Typ X erhalten, ohne das Objekt type aufzurufen, das X-Objekte erzeugt! Wenn set.__or__ nicht __new__ aufruft, ist es formal verpflichtet, set -Objekte anstelle von Unterklassenobjekten zurückzugeben.

Aber wenn Sie den Post mit nosklo oben notieren, macht Ihr ursprüngliches Verhalten keinen Sinn. Der Set.__or__ -Operator sollte keines der Quellobjekte wieder verwenden, um sein Ergebnis zu konstruieren, sondern sollte einen neuen erstellen, in diesem Fall sollte foo "default" !

sein

Praktisch sollte jeder, der macht diese Operatoren überladen, damit er weiß, welche Kopie von foo verwendet wird. Wenn es nicht davon abhängig ist, dass die Foosets kombiniert werden, können Sie es als Klassenstandard festlegen. In diesem Fall wird es berücksichtigt, da das neue Objekt denkt, dass es vom Unterklasse-Typ ist.

Was ich meine, ist, dass Ihr Beispiel irgendwie funktionieren würde, wenn Sie das getan hätten:

%Vor%     
Jon Obermark 07.09.2012 13:53
quelle
2

set1 | set2 ist eine Operation, die keine der vorhandenen set ändert, sondern stattdessen eine neue set zurückgibt. Der neue set wird erstellt und zurückgegeben. Es gibt keine Möglichkeit, die arbrity -Attribute automatisch von einem oder beiden set s in den neu erstellten set zu kopieren, ohne den Operator | selbst durch Definieren der Methode __or__ .

%Vor%

Drucke:

%Vor%     
nosklo 28.04.2009 15:29
quelle
2

Es sieht so aus, als setze% um_de% im c-Code . Wie auch immer, Sie werden eine Instanz von __init__ beenden, es wird keine Chance geben das Feld zu kopieren.

Abgesehen davon, dass ich die Methoden, die neue Sätze zurückgeben, außer Kraft gesetzt habe, bin ich mir nicht sicher, ob Sie in diesem Fall zu viel tun können. Set ist klar für eine gewisse Geschwindigkeit gebaut, so macht eine Menge Arbeit in c.

    
John Montgomery 28.04.2009 15:59
quelle
0

Unter der Annahme, dass die anderen Antworten korrekt sind, und das Überschreiben aller Methoden die einzige Möglichkeit ist, dies zu tun, hier ist mein Versuch einer mäßig eleganten Art, dies zu tun. Wenn mehrere Instanzvariablen hinzugefügt werden, muss nur ein Code geändert werden. Wenn ein neuer binärer Operator zum Set-Objekt hinzugefügt wird, wird dieser Code leider nicht funktionieren, aber ich glaube nicht, dass es einen Weg gibt, dies zu vermeiden. Kommentare willkommen!

%Vor%     
rog 28.04.2009 16:31
quelle
-2

Für mich funktioniert das perfekt mit Python 2.5.2 auf Win32. Verwenden Sie Ihre Klassendefinition und den folgenden Test:

%Vor%

Ich bekomme diese Ausgabe, was ich erwarte:

%Vor%     
Ber 28.04.2009 15:39
quelle