Ich habe eine benutzerdefinierte __dir__
Implementierung in meiner Basisklasse, die eine Liste aller benutzerdefinierten __slots__
Attribute zurückgeben soll. Dies funktioniert im Allgemeinen, aber es scheint eine sort
auf das Ergebnis zu tun, bevor es zurückkehrt, obwohl ich nicht programmiert habe, um dies zu tun (ich brauche die Attribute in der Reihenfolge genau die Reihenfolge, die sie zugewiesen sind).Benutzerdefiniert __dir __() gibt eine alphabetisch sortierte Liste von Attributen zurück
Ein Beispiel:
class A:
__slots__ = ['b', 'a']
def __dir__(self):
slot_attrs = []
for parent_class in reversed(type(self).__mro__[:-1]):
for attr in parent_class.__slots__:
slot_attrs.append(attr)
for attr in self.__slots__:
slot_attrs.append(attr)
return slot_attrs
class B(A):
__slots__ = ['c', 'd']
pass
class C(B):
__slots__ = []
pass
class D:
__slots__ = ['b', 'a']
def slots(self):
slot_attrs = []
for parent_class in reversed(type(self).__mro__[:-1]):
for attr in parent_class.__slots__:
slot_attrs.append(attr)
for attr in self.__slots__:
slot_attrs.append(attr)
return slot_attrs
class E(D):
__slots__ = ['c', 'd']
pass
class F(E):
pass
Die Ausgabe für slots()
und __dir__()
sollte, IMO, identisch.
sondern geschieht dies:
>>>c = C()
>>>f = F()
>>>print(dir(c))
['a', 'b', 'c', 'd']
>>>print(f.slots())
['b', 'a', 'c', 'd', 'c', 'd', 'c', 'd']
Ich kann Art von verstehen, dass es die Ausgabe alphabetisch sortiert, wenn dir()
mit - das ist documented in the docs. Es sieht jedoch aus wie ein Fehler - oder zumindest ein unerwartetes Verhalten für mich -, dass es die Ausgabe sortiert, obwohl ich eine benutzerdefinierte __dir__
Methode definiert habe.
Die zweite Ausgabe wirft mich einfach komplett aus meinem Spiel. Es schlägt vor, dass dir
auch eine Art von Filter verwendet, möglicherweise eine set
doppelte Ausgaben zu vermeiden, da der Code identisch ist, aber Aufruf slots()
gibt doppelte Werte zurück.
Ich weder A) verstehe, warum es das in erster Linie tut, noch B) was auf der Erde tut dir
tut nach allem.
Irgendwelche Hinweise hier?
bearbeiten:
Der zweite Fall ist solved- __mro__
enthält die Klasse des Anrufers sowie alle Klassen aus erbt - also die Klasse zweimal enthalten ist. d.h .:
>>>F.__mro__
(<class '__main__.F'>, <class '__main__.E'>, <class '__main__.D'>, <class 'object'>)
bearbeiten 2:
Die Handlung verdichtet. Die Frage in den Kommentaren verwiesen Schuppen ein kleines bisschen mehr Licht auf die Quelle dieses Verhalten:
>>Couldn't __dir__ also be allowed to return a tuple?
no, because tuples are not sortable, and i don't want to
over complicate the c-side code of PyObject_Dir.
having __dir__ returning only a list is equivalent to
__repr__ returning only strings.
Dies geht aus dem C-Quellcode stammt, etwas zu sein, aus der Zeit vor __dir__
umgesetzt wurde.
bearbeiten 3:
Ich habe eine issue on python's bug tracker geöffnet. Mal sehen, was der Konsens ist. Allerdings erwarte ich, dass dies auf den Backburner (wenn überhaupt) gesetzt wird, da dir()
, afaik, in erster Linie für die Inspektion in IDLE und dergleichen ausgelegt ist.
werden alle nicht eindeutigen Elemente entfernt werden, da Sie keinen Zugriff auf Methoden mit dem gleichen Namen in Python haben. 'dir' ruft nur Ihre benutzerdefinierte Methode auf, post-verarbeitet sie jedoch, um sie mit der Dokumentation zu kompilieren. –
Eigentlich entfernt ID sie nicht - ich habe es gerade getestet, es hält sie auch.Ich habe gerade '__slots__' zweimal von' F' hinzugefügt. – nlsdfnbch
Es scheint immer noch wie unerwartetes Verhalten. Wenn 'dir()' '__dir __()' aufruft, dann würde ich erwarten, dass es genau so läuft, wie ich es sage, und nicht hinter den Kulissen noch Voodoo machen. – nlsdfnbch