Python @ vara: kuidas seda kasutada ja miks? - Programiz

Selles õpetuses saate teada Python @property sisekujundaja kohta; pütooniline viis kasutada gettereid ja settereid objektorienteeritud programmeerimisel.

Pythoni programmeerimine pakub meile sisseehitatud @propertydekoraatorit, mis muudab getteri ja setterite kasutamise objektorienteeritud programmeerimisel palju lihtsamaks.

Enne kui läheme detailidesse selle üle, mis on @propertydekoraator, ehitame kõigepealt intuitsiooni selle kohta, miks seda üldse vaja oleks.

Klass ilma Getters ja Setters

Oletame, et otsustame teha klassi, mis hoiab temperatuuri Celsiuse kraadides. Samuti rakendaks see meetodi temperatuuri teisendamiseks Fahrenheiti kraadiks. Üks viis seda teha on järgmine:

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

Saame sellest klassist objekte teha ja temperatureatribuudiga manipuleerida vastavalt soovile:

 # 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())

Väljund

 37 98.60000000000001

Fahrenheitiks teisendamise lisakümnendkohad on tingitud ujukoma aritmeetilisest veast. Lisateabe saamiseks külastage Pythoni ujukoma aritmeetilist viga.

Alati, kui omistame või leiame mis tahes objekti atribuudi, nagu temperatureeespool näidatud, otsib Python seda objekti sisseehitatud __dict__sõnastiku atribuudist.

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

Seetõttu man.temperaturemuutub sisemiselt man.__dict__('temperature').

Getteri ja setteri kasutamine

Oletame, et soovime laiendada eespool määratletud Celsiuse klassi kasutatavust. Me teame, et ühegi objekti temperatuur ei saa tõusta alla -273,15 kraadi Celsiuse järgi (absoluutne null termodünaamikas)

Selle väärtusepiirangu rakendamiseks värskendame oma koodi.

Ülalnimetatud piirangu ilmne lahendus on atribuudi peitmine temperature(selle privaatseks muutmine) ja uute manipuleerimismeetodite määratlemine. Seda saab teha järgmiselt:

 # 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

Nagu näeme, tutvustab ülaltoodud meetod kahte uut get_temperature()ja set_temperature()meetodit.

Lisaks temperatureasendati _temperature. _Alguses alljooni kasutatakse Pythoni privaatsete muutujate tähistamiseks.

Kasutame nüüd seda rakendust:

 # 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())

Väljund

 37 98.60000000000001 Jälgimine (viimane kõne viimati): fail "", rida 30, failis "", rida 16, set_temperature ValueError: Temperatuur alla -273,15 pole võimalik.

Selle värskendusega rakendati uus piirang edukalt. Meil pole enam lubatud temperatuuri seada alla -273,15 kraadi Celsiuse järgi.

Märkus . Privaatseid muutujaid Pythonis tegelikult ei eksisteeri. On lihtsalt norme, mida tuleb järgida. Keel ise ei kehtesta mingeid piiranguid.

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

Kuid suurem probleem eespool värskendus on, et kõik programmid, mis rakendatakse meie eelmise klassi pea muutma oma koodi obj.temperature, et obj.get_temperature()kõik väljendid nagu obj.temperature = valon obj.set_temperature(val).

See ümbertegemine võib tekitada probleeme sadade tuhandete koodiridade käsitlemisel.

Kokkuvõttes ei olnud meie uus värskendus tagurpidi ühilduv. Siin @propertytulebki appi.

Kinnisvara klass

Püütoniline viis ülaltoodud probleemiga tegelemiseks on propertyklassi kasutamine. Koodi värskendamiseks toimige järgmiselt.

 # 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)

Lisasime print()funktsiooni sisse get_temperature()ja set_temperature()jälgime selgelt, et neid täidetakse.

Koodi viimane rida muudab atribuudi objekti temperature. Lihtsamalt öeldes lisab atribuut liikme atribuudi juurdepääsudele ( ) mõne koodi ( get_temperatureja ).set_temperaturetemperature

Kasutame seda värskenduskoodi:

 # 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

Väljund

 Väärtuse seadmine… Väärtuse hankimine… 37 Väärtuse hankimine … 98.6000000000000001 Väärtuse seadistamine… Traceback (viimane kõne on viimane): fail "", rida 31, fail "", rida 18, set_temperature ValueViga: Temperatuur alla -273 pole võimalik

Nagu näeme, temperaturehelistab iga kood, mille väärtus get_temperature()on, sõnastiku (__dict__) otsingu asemel automaatselt . Sarnaselt temperaturehelistab iga kood, millele määratakse väärtus set_temperature().

Näeme isegi eespool, mida set_temperature()kutsuti isegi siis, kui me objekti lõime.

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

Kas oskate arvata, miks?

Põhjus on see, et objekti loomisel __init__()kutsutakse meetod välja. Sellel meetodil on joon self.temperature = temperature. See väljend helistab automaatselt set_temperature().

Samamoodi on igasugune juurdepääs, näiteks c.temperatureautomaatne helistamine get_temperature(). Seda teeb vara. Siin on veel mõned näited.

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

Kasutades propertynäeme, et väärtuspiirangu rakendamisel pole muudatusi vaja. Seega on meie rakendamine tagurpidi ühilduv.

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)

Need kaks koodijuppi on samaväärsed.

Programmeerijad, kes tunnevad Pythoni sisekujundajaid, tunnevad ära, et ülaltoodud konstruktsiooni saab dekoraatoritena rakendada.

Me ei saa isegi mitte määratleda nimed get_temperatureja set_temperaturekui need on tarbetud ja saastavad klassi nimeruumi.

Selleks kasutame temperaturenime uuesti , määratledes samal ajal oma getteri ja setteri funktsioonid. Vaatame, kuidas seda dekoraatorina rakendada:

 # 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)

Väljund

 Väärtuse seadmine… Väärtuse hankimine… 37 Väärtuse hankimine … 98.6000000000000001 Väärtuse seadistamine … Traceback (viimane kõne viimati): fail "", rida 29, failis "", rida 4, __init__ failis ", rida 18, temperatuuril ValueError: Temperatuur alla -273 ei ole võimalik

Ülaltoodud rakendamine on lihtne ja tõhus. See on soovitatav kasutamisviis property.

Huvitavad Artiklid...