Python @property: Hogyan kell használni és miért? - Programiz

Ebben az oktatóanyagban megismerheti a Python @property dekoratőrt; a getterek és a setterek objektum-orientált programozásban való használatának python módja.

A Python programozás beépített @propertydekorátort biztosít számunkra, amely sokkal könnyebbé teszi a getter és a seterek használatát az objektumorientált programozásban.

Mielőtt belemennénk a @propertydekoratőr részleteibe , először építsünk intuíciót arra, hogy miért is lenne erre szükség.

Osztály Getters és Setters nélkül

Tegyük fel, hogy úgy döntünk, hogy olyan osztályt készítünk, amely a hőmérsékletet Celsius-fokban tárolja. Ezenkívül megvalósít egy módszert a hőmérséklet Fahrenheit fokokra való átszámítására. Ennek egyik módja a következő:

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

Készíthetünk objektumokat ebből az osztályból, és az temperatureattribútumot tetszés szerint kezelhetjük :

 # Basic method of setting and getting attributes in Python class Celsius: def __init__(self, temperature=0): self.temperature = temperature def to_fahrenheit(self): return (self.temperature * 1.8) + 32 # Create a new object human = Celsius() # Set the temperature human.temperature = 37 # Get the temperature attribute print(human.temperature) # Get the to_fahrenheit method print(human.to_fahrenheit())

Kimenet

 37 98.60000000000001

A plusz tizedesjegyek a Fahrenheit-re történő átszámításkor a lebegőpontos számtani hibának köszönhetők. További információkért keresse fel a Python lebegőpontos aritmetikai hibát.

Amikor hozzárendelünk vagy lekérünk bármilyen objektumattribútumot, mint temperaturea fent látható, a Python az objektum beépített __dict__szótárattribútumában keresi .

 >>> human.__dict__ ('temperature': 37)

Ezért man.temperaturebelsőleg válik man.__dict__('temperature').

Getters és Setters használata

Tegyük fel, hogy ki akarjuk terjeszteni a fentiekben meghatározott Celsius-osztály használhatóságát. Tudjuk, hogy egyetlen tárgy hőmérséklete sem érheti el a -273,15 Celsius fokot (abszolút nulla a termodinamikában)

Frissítsük kódunkat, hogy megvalósítsuk ezt az értékkorlátot.

A fenti korlátozás kézenfekvő megoldása lesz az attribútum elrejtése temperature(priváttá tétele), valamint új getter és setter módszerek meghatározása az manipulálására. Ez a következőképpen tehető meg:

 # Making Getters and Setter methods class Celsius: def __init__(self, temperature=0): self.set_temperature(temperature) def to_fahrenheit(self): return (self.get_temperature() * 1.8) + 32 # getter method def get_temperature(self): return self._temperature # setter method def set_temperature(self, value): if value < -273.15: raise ValueError("Temperature below -273.15 is not possible.") self._temperature = value

Mint láthatjuk, a fenti módszer két újat get_temperature()és módszert vezet be set_temperature().

Továbbá temperatureváltotta _temperature. A _kezdeti aláhúzás a privát változók jelölésére szolgál a Pythonban.

Most használjuk ezt a megvalósítást:

 # Making Getters and Setter methods class Celsius: def __init__(self, temperature=0): self.set_temperature(temperature) def to_fahrenheit(self): return (self.get_temperature() * 1.8) + 32 # getter method def get_temperature(self): return self._temperature # setter method def set_temperature(self, value): if value < -273.15: raise ValueError("Temperature below -273.15 is not possible.") self._temperature = value # Create a new object, set_temperature() internally called by __init__ human = Celsius(37) # Get the temperature attribute via a getter print(human.get_temperature()) # Get the to_fahrenheit method, get_temperature() called by the method itself print(human.to_fahrenheit()) # new constraint implementation human.set_temperature(-300) # Get the to_fahreheit method print(human.to_fahrenheit())

Kimenet

 37 98.60000000000001 Traceback (a legutóbbi hívás utoljára): "" fájl, 30. sor, a "" fájlban, 16. sor, a set_temperature ValueError: -273,15 alatti hőmérséklet nem lehetséges.

Ez a frissítés sikeresen végrehajtotta az új korlátozást. Már nem szabad a hőmérsékletet -273,15 Celsius fok alá állítani.

Megjegyzés : A privát változók valójában nem léteznek a Pythonban. Egyszerűen normákat kell követni. Maga a nyelv nem alkalmaz semmilyen korlátozást.

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

Azonban a nagyobb probléma a fenti változtatás az, hogy a programok végrehajtása a korábbi osztályba módosítani a kódot obj.temperature, hogy obj.get_temperature()minden olyan kifejezések, mint obj.temperature = vala obj.set_temperature(val).

Ez a visszafejlesztés problémákat okozhat, miközben több százezer kódsorral foglalkozik.

Összességében elmondható, hogy új frissítésünk nem volt kompatibilis a hátrafelé. Itt @propertyjön a mentés.

Az ingatlan osztály

A fenti probléma kezelésének python módja az propertyosztály használata . Így frissíthetjük kódunkat:

 # using property class class Celsius: def __init__(self, temperature=0): self.temperature = temperature def to_fahrenheit(self): return (self.temperature * 1.8) + 32 # getter def get_temperature(self): print("Getting value… ") return self._temperature # setter def set_temperature(self, value): print("Setting value… ") if value < -273.15: raise ValueError("Temperature below -273.15 is not possible") self._temperature = value # creating a property object temperature = property(get_temperature, set_temperature)

Felvettünk egy print()funkciót belül get_temperature()és set_temperature()annak egyértelmű megfigyelésére, hogy végrehajtják őket.

A kód utolsó sora tulajdonságobjektumot alkot temperature. Egyszerűen fogalmazva, a tulajdonság néhány kódot ( get_temperatureés set_temperature) csatol a tagattribútum hozzáférésekhez ( temperature).

Használjuk ezt a frissítési kódot:

 # using property class class Celsius: def __init__(self, temperature=0): self.temperature = temperature def to_fahrenheit(self): return (self.temperature * 1.8) + 32 # getter def get_temperature(self): print("Getting value… ") return self._temperature # setter def set_temperature(self, value): print("Setting value… ") if value < -273.15: raise ValueError("Temperature below -273.15 is not possible") self._temperature = value # creating a property object temperature = property(get_temperature, set_temperature) human = Celsius(37) print(human.temperature) print(human.to_fahrenheit()) human.temperature = -300

Kimenet

 Beállítási érték… Érték beolvasása … 37 Érték beolvasása … 98.6000000000000001 Beállítási érték … Traceback (a legutóbbi hívás utolsó): Fájl "" fájl, 31. sor, a Fájl "" sor, 18. sor, a set_temperature értékben Hiba: -273 alatti hőmérséklet nem lehetséges

Mint láthatjuk, minden olyan kód, amely lekérdezi az értékét, temperatureautomatikusan felhív get_temperature()egy szótár (__dict__) keresés helyett. Hasonlóképpen, minden olyan kód, amelyhez értéket rendel, temperatureautomatikusan hív set_temperature().

Fent is láthatjuk, set_temperature()amelyet akkor is hívtak, amikor objektumot hoztunk létre.

 >>> human = Celsius(37) Setting value… 

Kitalálod miért?

Ennek oka az, hogy amikor egy objektum létrehozásra kerül, a __init__()metódust meghívják. Ez a módszer rendelkezik a vonallal self.temperature = temperature. Ez a kifejezés automatikusan hív set_temperature().

Hasonlóképpen, bármilyen hozzáférés, például az c.temperatureautomatikus hívások get_temperature(). Ezt teszi a tulajdonság. Íme még néhány példa.

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

A használatával propertyláthatjuk, hogy nincs szükség módosításra az értékkorlát megvalósításában. Így megvalósításunk visszafelé kompatibilis.

Note: The actual temperature value is stored in the private _temperature variable. The temperature attribute is a property object which provides an interface to this private variable.

The @property Decorator

In Python, property() is a built-in function that creates and returns a property object. The syntax of this function is:

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

where,

  • fget is function to get value of the attribute
  • fset is function to set value of the attribute
  • fdel is function to delete the attribute
  • doc is a string (like a comment)

As seen from the implementation, these function arguments are optional. So, a property object can simply be created as follows.

 >>> property() 

A property object has three methods, getter(), setter(), and deleter() to specify fget, fset and fdel at a later point. This means, the line:

 temperature = property(get_temperature,set_temperature)

can be broken down as:

 # make empty property temperature = property() # assign fget temperature = temperature.getter(get_temperature) # assign fset temperature = temperature.setter(set_temperature)

Ez a két kód egyenértékű.

A Python Decoratorokat ismerő programozók felismerhetik, hogy a fenti konstrukció dekorátorként is megvalósítható.

Mi is nem határozza meg a nevét get_temperature, és set_temperaturemivel azok szükségtelen és szennyezik az osztály névtér.

Ehhez újból felhasználjuk a temperaturenevet, miközben meghatározzuk a getter és setter függvényeinket. Nézzük meg, hogyan lehet ezt dekoratőrként megvalósítani:

 # Using @property decorator 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("Getting value… ") return self._temperature @temperature.setter def temperature(self, value): print("Setting value… ") if value < -273.15: raise ValueError("Temperature below -273 is not possible") self._temperature = value # create an object human = Celsius(37) print(human.temperature) print(human.to_fahrenheit()) coldest_thing = Celsius(-300)

Kimenet

 Érték beállítása … Érték beolvasása … 37 Érték beolvasása … 98.6000000000000001 Beállítási érték … Traceback (legutóbbi hívás utoljára): "" fájl, 29. sor, a "" fájlban, 4. sor, a __init__ fájl "" sorban, 18. sor, a hőmérséklet ValueError: -273 alatti hőmérséklet nem lehetséges

A fenti megvalósítás egyszerű és hatékony. Ez az ajánlott felhasználási mód property.

érdekes cikkek...