Python @property: How to Use it and Why? - Programiz

文章推薦指數: 80 %
投票人數:10人

The @property Decorator CourseIndex ExploreProgramiz Python JavaScript C C++ Java Kotlin Swift C# DSA StartLearningPython ExplorePythonExamples PopularTutorials GettingStartedWithPython PythonifStatement whileLoopinPython PythonLists DictionariesinPython Viewalltutorials PopularExamples Addtwonumbers Checkprimenumber Findthefactorialofanumber PrinttheFibonaccisequence Checkleapyear Viewallexamples ReferenceMaterials Built-inFunctions ListMethods DictionaryMethods StringMethods Viewall LearningPaths Challenges LearnPythonInteractively TryforFree Courses BecomeaPythonMaster BecomeaCMaster ViewallCourses Python JavaScript C C++ Java Kotlin Swift C# DSA StartLearning Python PopularTutorials GettingStartedWithPython PythonifStatement whileLoopinPython PythonLists DictionariesinPython Viewalltutorials ReferenceMaterials Built-inFunctions ListMethods DictionaryMethods StringMethods Viewall Python JavaScript C C++ Java Kotlin ExplorePythonExamples PopularExamples Addtwonumbers Checkprimenumber Findthefactorialofanumber PrinttheFibonaccisequence Checkleapyear Viewallexamples PythonIntroduction GettingStarted KeywordsandIdentifier Statements&Comments PythonVariables PythonDataTypes PythonTypeConversion PythonI/OandImport PythonOperators PythonNamespace PythonFlowControl Pythonif...else PythonforLoop PythonwhileLoop Pythonbreakandcontinue PythonPass PythonFunctions PythonFunction FunctionArgument PythonRecursion AnonymousFunction Global,LocalandNonlocal PythonGlobalKeyword PythonModules PythonPackage PythonDatatypes PythonNumbers PythonList PythonTuple PythonString PythonSet PythonDictionary PythonFiles PythonFileOperation PythonDirectory PythonException ExceptionHandling User-definedException PythonObject&Class PythonOOP PythonClass PythonInheritance MultipleInheritance OperatorOverloading PythonAdvancedTopics PythonIterator PythonGenerator PythonClosure PythonDecorators PythonProperty PythonRegEx PythonExamples PythonDateandtime PythondatetimeModule Pythondatetime.strftime() Pythondatetime.strptime() Currentdate&time Getcurrenttime Timestamptodatetime PythontimeModule Pythontime.sleep() RelatedTopics Pythonproperty() PythonObjectOrientedProgramming Pythonsetattr() Pythonvars() PythonProgrammingBuilt-inFunctions PythonObjectsandClasses Python@propertydecorator Inthistutorial,youwilllearnaboutPython@propertydecorator;apythonicwaytousegettersandsettersinobject-orientedprogramming. Pythonprogrammingprovidesuswithabuilt-in@propertydecoratorwhichmakesusageofgetterandsettersmucheasierinObject-OrientedProgramming. Beforegoingintodetailsonwhat@propertydecoratoris,letusfirstbuildanintuitiononwhyitwouldbeneededinthefirstplace. ClassWithoutGettersandSetters LetusassumethatwedecidetomakeaclassthatstoresthetemperatureindegreesCelsius.ItwouldalsoimplementamethodtoconvertthetemperatureintodegreesFahrenheit.Onewayofdoingthisisasfollows: classCelsius: def__init__(self,temperature=0): self.temperature=temperature defto_fahrenheit(self): return(self.temperature*1.8)+32 Wecanmakeobjectsoutofthisclassandmanipulatethetemperatureattributeaswewish: #BasicmethodofsettingandgettingattributesinPython classCelsius: def__init__(self,temperature=0): self.temperature=temperature defto_fahrenheit(self): return(self.temperature*1.8)+32 #Createanewobject human=Celsius() #Setthetemperature human.temperature=37 #Getthetemperatureattribute print(human.temperature) #Gettheto_fahrenheitmethod print(human.to_fahrenheit()) Output 37 98.60000000000001 TheextradecimalplaceswhenconvertingintoFahrenheitisduetothefloatingpointarithmeticerror.Tolearnmore,visitPythonFloatingPointArithmeticError. Wheneverweassignorretrieveanyobjectattributeliketemperatureasshownabove,Pythonsearchesitintheobject'sbuilt-in__dict__dictionaryattribute. >>>human.__dict__ {'temperature':37} Therefore,man.temperatureinternallybecomesman.__dict__['temperature']. UsingGettersandSetters SupposewewanttoextendtheusabilityoftheCelsiusclassdefinedabove.Weknowthatthetemperatureofanyobjectcannotreachbelow-273.15degreesCelsius(AbsoluteZeroinThermodynamics) Let'supdateourcodetoimplementthisvalueconstraint. Anobvioussolutiontotheaboverestrictionwillbetohidetheattributetemperature(makeitprivate)anddefinenewgetterandsettermethodstomanipulateit.Thiscanbedoneasfollows: #MakingGettersandSettermethods classCelsius: def__init__(self,temperature=0): self.set_temperature(temperature) defto_fahrenheit(self): return(self.get_temperature()*1.8)+32 #gettermethod defget_temperature(self): returnself._temperature #settermethod defset_temperature(self,value): ifvalue",line30,in File"",line16,inset_temperature ValueError:Temperaturebelow-273.15isnotpossible. Thisupdatesuccessfullyimplementedthenewrestriction.Wearenolongerallowedtosetthetemperaturebelow-273.15degreesCelsius. Note:Theprivatevariablesdon'tactuallyexistinPython.Therearesimplynormstobefollowed.Thelanguageitselfdoesn'tapplyanyrestrictions. >>>human._temperature=-300 >>>human.get_temperature() -300 However,thebiggerproblemwiththeaboveupdateisthatalltheprogramsthatimplementedourpreviousclasshavetomodifytheircodefromobj.temperaturetoobj.get_temperature()andallexpressionslikeobj.temperature=valtoobj.set_temperature(val). Thisrefactoringcancauseproblemswhiledealingwithhundredsofthousandsoflinesofcodes. Allinall,ournewupdatewasnotbackwardscompatible.Thisiswhere@propertycomestorescue. ThepropertyClass Apythonicwaytodealwiththeaboveproblemistousethepropertyclass.Hereishowwecanupdateourcode: #usingpropertyclass classCelsius: def__init__(self,temperature=0): self.temperature=temperature defto_fahrenheit(self): return(self.temperature*1.8)+32 #getter defget_temperature(self): print("Gettingvalue...") returnself._temperature #setter defset_temperature(self,value): print("Settingvalue...") ifvalue",line31,in File"",line18,inset_temperature ValueError:Temperaturebelow-273isnotpossible Aswecansee,anycodethatretrievesthevalueoftemperaturewillautomaticallycallget_temperature()insteadofadictionary(__dict__)look-up.Similarly,anycodethatassignsavaluetotemperaturewillautomaticallycallset_temperature(). Wecanevenseeabovethatset_temperature()wascalledevenwhenwecreatedanobject. >>>human=Celsius(37) Settingvalue... Canyouguesswhy? Thereasonisthatwhenanobjectiscreated,the__init__()methodgetscalled.Thismethodhasthelineself.temperature=temperature.Thisexpressionautomaticallycallsset_temperature(). Similarly,anyaccesslikec.temperatureautomaticallycallsget_temperature().Thisiswhatpropertydoes.Hereareafewmoreexamples. >>>human.temperature Gettingvalue 37 >>>human.temperature=37 Settingvalue >>>c.to_fahrenheit() Gettingvalue 98.60000000000001 Byusingproperty,wecanseethatnomodificationisrequiredintheimplementationofthevalueconstraint.Thus,ourimplementationisbackwardcompatible. Note:Theactualtemperaturevalueisstoredintheprivate_temperaturevariable.Thetemperatureattributeisapropertyobjectwhichprovidesaninterfacetothisprivatevariable. The@propertyDecorator InPython,property()isabuilt-infunctionthatcreatesandreturnsapropertyobject.Thesyntaxofthisfunctionis: property(fget=None,fset=None,fdel=None,doc=None) where, fgetisfunctiontogetvalueoftheattribute fsetisfunctiontosetvalueoftheattribute fdelisfunctiontodeletetheattribute docisastring(likeacomment) Asseenfromtheimplementation,thesefunctionargumentsareoptional.So,apropertyobjectcansimplybecreatedasfollows. >>>property() Apropertyobjecthasthreemethods,getter(),setter(),anddeleter()tospecifyfget,fsetandfdelatalaterpoint.Thismeans,theline: temperature=property(get_temperature,set_temperature) canbebrokendownas: #makeemptyproperty temperature=property() #assignfget temperature=temperature.getter(get_temperature) #assignfset temperature=temperature.setter(set_temperature) Thesetwopiecesofcodesareequivalent. ProgrammersfamiliarwithPythonDecoratorscanrecognizethattheaboveconstructcanbeimplementedasdecorators. Wecanevennotdefinethenamesget_temperatureandset_temperatureastheyareunnecessaryandpollutetheclassnamespace. Forthis,wereusethetemperaturenamewhiledefiningourgetterandsetterfunctions.Let'slookathowtoimplementthisasadecorator: #Using@propertydecorator classCelsius: def__init__(self,temperature=0): self.temperature=temperature defto_fahrenheit(self): return(self.temperature*1.8)+32 @property deftemperature(self): print("Gettingvalue...") returnself._temperature @temperature.setter deftemperature(self,value): print("Settingvalue...") ifvalue



請為這篇文章評分?