Frage

Ich versuche, den Unterschied zwischen __getattr__ und __getattribute__ zu verstehen, aber ich bin es versagt.

Die Antwort auf die Frage Stack-Überlauf Unterschied zwischen __getattr__ vs __getattribute__ sagt:

  

__getattribute__ wird aufgerufen, bevor an den tatsächlichen Eigenschaften der Suche auf   das Objekt und kann so schwierig sein zu   korrekt umzusetzen. Sie können am Ende in   unendliche Rekursion sehr leicht.

Ich habe absolut keine Ahnung, was das bedeutet.

Dann geht es weiter zu sagen:

  

Sie wollen an Sicherheit grenzender Wahrscheinlichkeit __getattr__.

Warum?

Ich habe gelesen, dass, wenn __getattribute__ ausfällt, __getattr__ genannt wird. Warum also gibt es zwei verschiedene Methoden, um die gleiche Sache zu tun? Wenn mein Code implementiert die Klassen neuen Stils, was soll ich verwenden?

Ich suche für einige Code-Beispiele, diese Frage zu klären. Ich habe meine besten Kräfte gegoogelt, aber die Antworten, dass ich das Problem gründlich nicht diskutieren gefunden.

Wenn es eine Dokumentation, ich bin bereit, das zu lesen.

War es hilfreich?

Lösung

Einige Grundlagen zuerst.

Mit Objekten, müssen Sie mit ihren Attributen beschäftigen. Normalerweise tun instance.attribute wir. Manchmal brauchen wir mehr Kontrolle (wenn wir nicht den Namen des Attributs im Voraus).

Zum Beispiel würde instance.attribute getattr(instance, attribute_name) werden. Mit diesem Modell können wir das Attribut erhalten, indem Sie die attribute_name als String zurück.

Verwendung von __getattr__

Sie können auch eine Klasse sagen, wie mit Attributen befassen, die es nicht explizit verwalten und zu tun, dass über __getattr__ Verfahren.

Python wird diese Methode aufrufen, wenn Sie ein Attribut anfordern, die nicht bereits definiert wurde, so können Sie festlegen, was mit ihm zu tun.

Ein klassischer Anwendungsfall:

class A(dict):
    def __getattr__(self, name):
       return self[name]
a = A()
# Now a.somekey will give a['somekey']

Caveats und die Verwendung von __getattribute__

Wenn Sie jedes Attribut fangen müssen unabhängig davon, ob es existiert oder nicht , sondern __getattribute__ statt. Der Unterschied besteht darin, dass __getattr__ nur für Attribute aufgerufen wird, die eigentlich nicht existieren. Wenn Sie ein Attribut direkt gesetzt, das Attribut Referenzierung wird es abrufen, ohne __getattr__ aufrufen.

__getattribute__ ist es, alle Zeiten genannt.

Andere Tipps

__getattribute__ wird aufgerufen, wenn ein Attribut Zugriff auftritt.

class Foo(object):
    def __init__(self, a):
        self.a = 1

    def __getattribute__(self, attr):
        try:
            return self.__dict__[attr]
        except KeyError:
            return 'default'
f = Foo(1)
f.a

Dies wird Endlosschleife verursachen. Der Täter ist hier die Linie return self.__dict__[attr]. Nehmen wir an, (es ist nahe genug an der Wahrheit), dass alle Attribute in self.__dict__ und verfügbar durch ihren Namen gespeichert sind. Die Zeile

f.a

Versuche, das a Attribut f zuzugreifen. Dies erfordert f.__getattribute__('a'). __getattribute__ dann versucht, Last self.__dict__. __dict__ ist ein Attribut self == f und so Python f.__getattribute__('__dict__') ruft die wiederum versucht, das Attribut '__dict__ zugreifen‘. Dies ist eine unendliche Rekursion.

Wenn __getattr__ verwendet worden war, statt dann

  1. Es würde nie ausgeführt haben, weil f ein a Attribut hat.
  2. Wenn es gelaufen war, (lassen Sie uns sagen, dass Sie für f.b gefragt), dann wäre es nicht genannt worden __dict__ zu finden, weil es schon da ist und __getattr__ aufgerufen wird, nur wenn alle anderen Maßnahmen zur Suche nach dem Attribut versagt haben .

Der ‚richtige‘ Weg, um die oben Klasse mit __getattribute__ zu schreiben, ist

class Foo(object):
    # Same __init__

    def __getattribute__(self, attr):
        return super(Foo, self).__getattribute__(attr)

super(Foo, self).__getattribute__(attr) bindet die __getattribute__ Methode des nächsten Ort übergeordnete Klasse (formal, die nächste Klasse in der Methode Auflösung des Ordens Klasse oder MRO) auf das aktuelle Objekt self und dann ruft er und lässt, dass die Arbeit machen.

All diese Probleme vermieden wird durch __getattr__ mit der Python lässt tun es die normalste Sache , bis ein Attribut nicht gefunden wird. An diesem Punkt steuern Python Hände auf Ihre __getattr__ Methode über und lässt sie mit etwas einfallen lassen.

Es ist auch erwähnenswert, dass Sie in eine unendliche Rekursion mit __getattr__ laufen kann.

class Foo(object):
    def __getattr__(self, attr):
        return self.attr

Ich werde, dass man als Übung verlassen.

Ich denke, die anderen Antworten eine große Aufgabe, den Unterschied zwischen __getattr__ und __getattribute__ erklärt getan haben, aber eine Sache, die nicht klar sein könnte, ist, warum Sie __getattribute__ verwenden möchten. Die kühle Sache über __getattribute__ ist, dass es im Wesentlichen ermöglicht es Ihnen, den Punkt zu überlasten, wenn eine Klasse zugreifen. Auf diese Weise können Sie anpassen, wie Attribute auf einem niedrigen Niveau zugegriffen werden. Zum Beispiel nehme ich an, eine Klasse definieren möge, alle Methoden, die nur ein Selbst Argument werden als Eigenschaften behandelt:

# prop.py
import inspect

class PropClass(object):
    def __getattribute__(self, attr):
        val = super(PropClass, self).__getattribute__(attr)
        if callable(val):
            argcount = len(inspect.getargspec(val).args)
            # Account for self
            if argcount == 1:
                return val()
            else:
                return val
        else:
            return val

Und von dem interaktiven Interpreter:

>>> import prop
>>> class A(prop.PropClass):
...     def f(self):
...             return 1
... 
>>> a = A()
>>> a.f
1

Natürlich ist dies ein dummes Beispiel, und Sie würden wahrscheinlich nicht immer wollen, dies zu tun, aber es zeigt Ihnen die Leistung, die Sie überschreiben __getattribute__ erhalten können.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top