2016-02-10 4 views
9

Der folgende Code verhält sich in Python 2 und Python 3 anders, und ich bin nicht sicher, warum.Unterschied in "dir" zwischen Python 2 und 3

class Dataset(object): 
    def __getattr__(self, item): 
     if not item in dir(self): 
      print(item) 

a = Dataset() 
a.Hello 

Das Ergebnis in Python 3:

> Hello 

Das Ergebnis in Python 2:

__members__ 
__members__ 
__methods__ 
... 

ad infinitum, bis eine Rekursion Obergrenze erreicht ist. Was ist der Unterschied im Verhalten von "dir"?

Edit: Und gibt es einen Workaround? selbst. dict ist die offensichtliche Wahl, aber es enthält keine Funktionen, die sich als ein Problem in meinem Code herausstellt.

+2

Eigentlich haben kann, '__getattr __()' [sollte gar nicht aufgerufen werden] (https://docs.python.org/2/reference/datamodel.html#object.__getattr__), wenn das Attribut bereits vorhanden ist. – dhke

Antwort

6

Die Dokumentation für dir in Python 2.7 und 3.5 scheint identisch zu sein - es gibt keine Implementierungsdetails. Aber klar, dir() in Python 2 ruft __getattr__ auf, was die unendliche Rekursion verursacht.

jedoch beiden Dokumentationssätze sagen, dass

Weil dir() an einer interaktiven Eingabeaufforderung in erster Linie als Service für den Einsatz geliefert, versucht es eine interessante Reihe von Namen zu liefern mehr, als es zu liefern versucht ein rigoros oder konsistent definierter Satz von Namen, und sein detailliertes Verhalten kann sich über Releases hinweg ändern. Zum Beispiel sind Metaklassenattribute nicht in der Ergebnisliste, wenn das Argument eine Klasse ist.

Der Hinweis, dass es eine Bequemlichkeit ist, ist signifikant.

Wenn Sie Ihre __getattr__ ändern, um self.__dict__ statt dir() zu betrachten, verschwindet das Problem.

In [5]: class Dataset(object): 
      def __getattr__(self, item): 
      if not item in self.__dict__: 
       print(item) 
    ...:    

In [6]: a = Dataset() 

In [7]: a.Hello 
Hello 
+1

Die Bearbeitung über Funktionen wurde erst angezeigt, nachdem ich die Antwort – kdopen

+1

AFAIR gepostet habe, 'dir()' versucht, '__dir__' zu suchen. Da dieser nicht existiert, wird '__getattr __()' aufgerufen. Was ruft 'dir()' ... – dhke

3

Ohne den Quellcode zu untersuchen, kann ich nicht sagen, warum dies geschieht (obwohl ich habe einige Hypothesen), aber hier ist eine ziemlich einfache Abhilfe:

class Dataset(object): 
    def __getattr__(self, item): 
     try: 
      super(Dataset, self).__getattr__(item) 
     except AttributeError: 
      print(item) 
1

Es ist nicht erforderlich, zu prüfen, ob if not item in dir(self) innerhalb def __getattr__

__getattr__ nicht, wenn das Element in dir (Selbst-) aufgeführt wird aufgerufen werden Sie Ihren Code als

class Dataset(object): 
    x = 12 
    def __getattr__(self, item): 
     print(item) 

a = Dataset() 
a.Hello # print Hello 
a.x  # return 12 
Verwandte Themen