English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Python Grundlagen教程

Python Flusskontrolle

Python-Funktion

Python-Datentypen

Python Dateioperationen

Python Objekte und Klassen

Python Datum und Zeit

Erweiterte Kenntnisse in Python

Python Referenzhandbuch

Python-@property

Python hat ein großartiges Konzept namens 'Eigenschaft', das das Leben von objektorientierten Programmierern einfacher macht.

Bevor wir das @property definieren und vollständig verstehen, lassen Sie uns verstehen, warum es notwendig ist, es zu verwenden.

einer Instanz beginnen

Angenommen, Sie entscheiden sichErstellen Sie eineEine Klasse, die Temperaturen in Grad Celsius speichert. Sie wird auch eine Methode zur Umrechnung der Temperatur in Fahrenheit umsetzen. Ein solches Verfahren könnte wie folgt aussehen.

class Celsius:
    def __init__(self, temperature = 0):
        self.temperature = temperature
    def to_fahrenheit(self):
        return (self.temperature * 1.8) + 32

Wir können Objekte aus dieser Klasse erstellen und die Eigenschaft 'temperature' nach Bedarf manipulieren. Versuchen Sie dies im Python-Shell.

>>> # Erstellen Sie ein neues Objekt
>>> man = Celsius()
>>> # Setzen Sie die Temperatur
>>> man.temperature = 37
>>> # Erhalten Sie die Temperatur
>>> man.temperature
37
>>> # Erhalten Sie die Fahrenheit
>>> man.to_fahrenheit()
98.60000000000001

Bei der Umrechnung in Fahrenheit-Fahrenheit gibt es zusätzliche Dezimalstellen aufgrund von Fließkommadarstellungen (wenn der Python-Interpreter versucht1.1 + 2.2).

Wie oben gezeigt, suchen wir nach jedem Zuweisen oder Abrufen eines Objektsattributs (wietemperature) führt Python eine Suche im __dict__-Diktionär des Objekts durch.

>>> man.__dict__
{'temperature': 37}

Daher wird 'man.temperature' intern zu 'man.__dict__['temperature']'.

Nun, lassen Sie uns weiter annehmen, dass unser Kurs bei unseren Kunden sehr beliebt ist und sie ihn in ihren Programmen verwenden. Sie haben verschiedene Zuweisungen an Objekte vorgenommen.

Eines Tages kam ein vertrauenswürdiger Kunde zu uns und empfahl, dass die Temperatur nicht unter-273Kelsiusgrad (Thermodynamikstudenten könnten sagen, dass es tatsächlich)-273.15Kelsiusgrad), auch bekannt als Absolute Null, erfordert, dass wir diese Wertbeschränkung implementieren. Als Unternehmen, das der Kundenzufriedenheit verpflichtet ist, freuen wir uns über diesen Vorschlag und haben1.01Version (Aktualisierung der bestehenden Klasse).

Verwendung von Getter und Setter

Eine offensichtliche Methode zur Lösung dieser Einschränkung ist die Verbergence des Attributs 'temperature' (dieses wird als privat gesetzt) und die Definition neuer Getter- und Setter-Interfaces, um darauf zuzugreifen. Dies kann wie folgt erfolgen.

class Celsius:
    def __init__(self, temperature = 0):
        self.set_temperature(temperature)
    def to_fahrenheit(self):
        return(self.get_temperature()) * 1.8) + 32
    # new update
    def get_temperature(self):
        return self._temperature
    def set_temperature(self, value):
        if value < -273:
            raise ValueError("-273Grad sind unmöglich")
        self._temperature = value

Wir können aufgeteilt sehen, dass get_temperature() und set_temperature() neue Methoden definiert haben, sowie dass _temperature anstelle von temperature verwendet wird. Ein Unterstrich (_) am Anfang zeigt an, dass es sich in Python um eine private Variable handelt.

>>> c = Celsius(-277)
Traceback (most recent call last):
...
ValueError: Temperature below -273 is not possible
>>> c = Celsius(37)
>>> c.get_temperature()
37
>>> c.set_temperature(10)
>>> c.set_temperature(-300)
Traceback (most recent call last):
...
ValueError: Temperature below -273 is not possible

Diese Aktualisierung hat erfolgreich neue Einschränkungen implementiert. Wir sind nicht mehr erlaubt, die Temperatur auf unter-273.

Bitte beachten Sie, dass es in Python keine privaten Variablen gibt. Es genügt, einige Normen zu befolgen. Die Sprache selbst hat keine Beschränkungen.

>>> c._temperature = -300
>>> c.get_temperature()
-300

Dies ist jedoch kein großes Problem. Das größte Problem dieser Aktualisierung liegt darin, dass alle Clienten, die den vorherigen Klasse implementiert haben, ihre Codes von obj.temperature auf obj.get_temperature() ändern müssen und alle Zuweisungen (z.B. obj.temperature = val zu obj.set_temperature(val) geändert).

Diese Refactoring kann Kunden in Schwierigkeiten bringen, da es tausende von Zeilen Code gibt.

Zusammenfassend gesagt, unsere neue Aktualisierung ist nicht rückwärts kompatibel. Dies ist der Ort, an dem @property funktioniert.

Die Kraft von @property

Python behandelt das oben genannte Problem durch die Verwendung von property. Wir können es so umsetzen.

class Celsius:
    def __init__(self, temperature = 0):
        self.temperature = temperature
    def to_fahrenheit(self):
        return (self.temperature * 1.8) + 32
    def get_temperature(self):
        print("Gewonnener Wert")
        return self._temperature
    def set_temperature(self, value):
        if value < -273:
            raise ValueError("Unterkühlung273Grad sind unmöglich")
        print("Eingestellter Wert")
        self._temperature = value
    temperature = property(get_temperature, set_temperature)

Und einmal ausgeführt, geben Sie im Shell die folgenden Codes aus.

>>> c = Celsius()

Wir haben in get temperature() und set temperature() die Funktion print() hinzugefügt, um deren Ausführung klar zu beobachten.

Die letzte Zeile des Codes erstellt ein Property-Objekt temperature. Kurz gesagt, das Attribut hängt einige Codes (get_temperature und set_temperature) an den Mitgliedsattribut-Zugriff (temperature) an.

任何检索温度值的代码都将自动调用get_temperature()而不是字典(__dict__)查找。 同样,任何为温度分配值的代码都会自动调用set_temperature()。 这是Python中的一项很酷的功能。

我们可以在上面看到即使创建对象时也会调用set_temperature()。

你能猜出为什么吗?

原因是创建对象时,将调用__init__()方法。 此方法的行是self.temperature = temperature。 此分配自动称为set_temperature()。

>>> c.temperature
Getting value
0

同样,任何访问如c.temperature都会自动调用get_temperature()。 这就是属性的作用。 这里还有一些实例。

>>> c.temperature = 37
Setting value
>>> c.to_fahrenheit()
Getting value
98.60000000000001

通过使用属性,我们可以看到,我们修改了类并实现了值约束,而无需更改客户端代码。因此,我们的实现是向后兼容的。

最后请注意,实际温度值存储在私有变量_temperature中。 temperature属性是一个属性对象,它提供了与此私有变量的接口。

深入了解property

在Python中,property()是一个内置函数,用于创建并返回属性对象。该函数的签名是

property(fget=None, fset=None, fdel=None, doc=None)

其中,fget为获取属性值的函数,fset为设置属性值的函数,fdel为删除属性的函数,doc为字符串(如注释)。从实现中可以看出,这些函数参数是可选的。因此,可以简单地按照以下方式创建属性对象。

>>> property()
<property object at 0x000000000>3239B38>

属性对象有三个方法,getter()、setter()和deleter(),用于稍后指定fget、fset和fdel。这意味着

temperature = property(get_temperature, set_temperature)

können auch in zwei Teile aufgeteilt werden

# Erstellen eines leeren Attributes
temperature = property()
# Setzen von fget
temperature = temperature.getter(get_temperature)
# Setzen von fset
temperature = temperature.setter(set_temperature)

Diese beiden Zeilen von Code sind äquivalent.

bekanntDekoratoren in PythonProgrammierer können erkennen, dass die obigen Konstrukte als Dekoratoren implementiert werden können.

Wir können noch einen Schritt weitergehen, indem wir den Namen get_temperature, set_temperature nicht definieren, da sie nicht erforderlich sind und den Namensraum der Klasse beeinflussen könnten. Dazu verwenden wir bei der Definition der Getter- und Setter-Funktionen den Namen temperature. Das ist möglich.

class Celsius:
    def __init__(self, temperature = 0):
        self._temperature = temperature
    def to_fahrenheit(self):
        return (self.temperature * 1.8) + 32
    @property
    def temperature(self):
        print("Wert erhalten")
        return self._temperature
    @temperature.setter
    def temperature(self, value):
        if value < -273:
            raise ValueError("Unterkühlung273Grad sind unmöglich")
        print("Eingestellter Wert")
        self._temperature = value

Die obige Implementierung ist eine einfache und empfohlene Methode zur Erstellung von Eigenschaften. Wenn Sie nach Eigenschaften in Python suchen, werden Sie wahrscheinlich diese Arten von Konstrukten antreffen.

Gut, das ist's für heute.