The @property Decorator in Python: Its Use Cases ...

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

A decorator function is basically a function that adds new functionality to a function that is passed as argument. Using a decorator function is ... Search Submityoursearchquery Forum Donate Learntocode—free3,000-hourcurriculum EstefaniaCassingenaNavone 🔹MeetPropertiesWelcome!Inthisarticle,youwilllearnhowtoworkwiththe@propertydecoratorinPython.Youwilllearn:TheadvantagesofworkingwithpropertiesinPython.Thebasicsofdecoratorfunctions:[email protected]@propertytodefinegetters,setters,anddeleters.1️⃣AdvantagesofPropertiesinPythonLet'sstartwithalittlebitofcontext.WhywouldyouusepropertiesinPython?Propertiescanbeconsideredthe"Pythonic"wayofworkingwithattributesbecause:Thesyntaxusedtodefinepropertiesisveryconciseandreadable.Youcanaccessinstanceattributesexactlyasiftheywerepublicattributeswhileusingthe"magic"ofintermediaries(gettersandsetters)tovalidatenewvaluesandtoavoidaccessingormodifyingthedatadirectly.Byusing@property,youcan"reuse"thenameofapropertytoavoidcreatingnewnamesforthegetters,setters,anddeleters.Theseadvantagesmakepropertiesareallyawesometooltohelpyouwritemoreconciseandreadablecode.?2️⃣IntrotoDecoratorsAdecoratorfunctionisbasicallyafunctionthataddsnewfunctionalitytoafunctionthatispassedasargument.Usingadecoratorfunctionislikeaddingchocolatesprinklestoanicecream?.Itletsusaddnewfunctionalitytoanexistingfunctionwithoutmodifyingit.Intheexamplebelow,youcanseewhatatypicaldecoratorfunctionlookslikeinPython:defdecorator(f): defnew_function(): print("ExtraFunctionality") f() returnnew_function @decorator definitial_function(): print("InitialFunctionality") initial_function()Let'sanalyzetheseelementsindetail:Wefirstfindthedecoratorfunctiondefdecorator(f)(thesprinkles✨)thattakesafunctionfasanargument.defdecorator(f): defnew_function(): print("ExtraFunctionality") f() returnnew_functionThisdecoratorfunctionhasannestedfunction,new_function.Noticehowfiscalledinsidenew_functiontoachievethesamefunctionalitywhileaddingnewfunctionalitybeforethefunctioncall(wecouldalsoaddnewfunctionalityafterthefunctioncall).Thedecoratorfunctionitselfreturnsthenestedfunctionnew_function.Then(below),wefindthefunctionthatwillbedecorated(theicecream?)initial_function.Noticetheverypeculiarsyntax(@decorator)abovethefunctionheader.@decorator definitial_function(): print("InitialFunctionality") initial_function()Ifwerunthecode,weseethisoutput:ExtraFunctionality InitialFunctionalityNoticehowthedecoratorfunctionrunsevenifweareonlycallinginitial_function().Thisisthemagicofadding@decorator?.💡Note:Ingeneral,wewouldwrite@,replacingthenameofthedecoratorfunctionafterthe@symbol.Iknowyoumaybeasking:howisthisrelatedtothe@property?The@propertyisabuilt-indecoratorfortheproperty()functioninPython.Itisusedtogive"special"functionalitytocertainmethodstomakethemactasgetters,setters,ordeleterswhenwedefinepropertiesinaclass.Nowthatyouarefamiliarwithdecorators,let'sseearealscenariooftheuseof@property!🔸Real-WorldScenario:@propertyLet'ssaythatthisclassispartofyourprogram.YouaremodelingahousewithaHouseclass(atthemoment,theclassonlyhasapriceinstanceattributedefined):classHouse: def__init__(self,price): self.price=priceThisinstanceattributeispublicbecauseitsnamedoesn'thavealeadingunderscore.Sincetheattributeiscurrentlypublic,itisverylikelythatyouandotherdevelopersinyourteamaccessedandmodifiedtheattributedirectlyinotherpartsoftheprogramusingdotnotation,likethis:#Accessvalue obj.price #Modifyvalue obj.price=40000💡Tip:objrepresentsavariablethatreferencesaninstanceofHouse.Sofareverythingisworkinggreat,right?Butlet'ssaythatyouareaskedtomakethisattributeprotected(non-public)andvalidatethenewvaluebeforeassigningit.Specifically,youneedtocheckifthevalueisapositivefloat.Howwouldyoudothat?Let'ssee.ChangingyourCodeAtthispoint,ifyoudecidetoaddgettersandsetters,youandyourteamwillprobablypanic?.Thisisbecauseeachlineofcodethataccessesormodifiesthevalueoftheattributewillhavetobemodifiedtocallthegetterorsetter,respectively.Otherwise,thecodewillbreak⚠️.#Changedfromobj.price obj.get_price() #Changedfromobj.price=40000 obj.set_price(40000)But...Propertiescometotherescue!With@property,youandyourteamwillnotneedtomodifyanyofthoselinesbecauseyouwillabletoaddgettersandsetters"behindthescenes"withoutaffectingthesyntaxthatyouusedtoaccessormodifytheattributewhenitwaspublic.Awesome,right? 🔹@property:SyntaxandLogicIfyoudecidetouse@property,yourclasswilllookliketheexamplebelow:classHouse: def__init__(self,price): self._price=price @property defprice(self): returnself._price @price.setter defprice(self,new_price): ifnew_price>0andisinstance(new_price,float): self._price=new_price else: print("Pleaseenteravalidprice") @price.deleter defprice(self): delself._priceSpecifically,youcandefinethreemethodsforaproperty:Agetter-toaccessthevalueoftheattribute.Asetter-tosetthevalueoftheattribute.Adeleter-todeletetheinstanceattribute.Priceisnow"Protected"Pleasenotethatthepriceattributeisnowconsidered"protected"becauseweaddedaleadingunderscoretoitsnameinself._price:self._price=priceInPython,byconvention,whenyouaddaleadingunderscoretoaname,youaretellingotherdevelopersthatitshouldnotbeaccessedormodifieddirectlyoutsideoftheclass.Itshouldonlybeaccessedthroughintermediaries(gettersandsetters)iftheyareavailable.🔸GetterHerewehavethegettermethod:@property defprice(self): returnself._priceNoticethesyntax:@property-Usedtoindicatethatwearegoingtodefineaproperty.Noticehowthisimmediatelyimprovesreadabilitybecausewecanclearlyseethepurposeofthismethod.defprice(self)-Theheader.Noticehowthegetterisnamedexactlylikethepropertythatwearedefining:price.Thisisthenamethatwewillusetoaccessandmodifytheattributeoutsideoftheclass.Themethodonlytakesoneformalparameter,self,whichisareferencetotheinstance.returnself._price-Thislineisexactlywhatyouwouldexpectinaregulargetter.Thevalueoftheprotectedattributeisreturned.Hereisanexampleoftheuseofthegettermethod:>>>house=House(50000.0)#Createinstance >>>house.price#Accessvalue 50000.0Noticehowweaccessthepriceattributeasifitwereapublicattribute.Wearenotchangingthesyntaxatall,butweareactuallyusingthegetterasanintermediarytoavoidaccessingthedatadirectly.🔹SetterNowwehavethesettermethod:@price.setter defprice(self,new_price): ifnew_price>0andisinstance(new_price,float): self._price=new_price else: print("Pleaseenteravalidprice")Noticethesyntax:@price.setter-Usedtoindicatethatthisisthesettermethodforthepriceproperty.Noticethatwearenotusing@property.setter,weareusing@price.setter.Thenameofthepropertyisincludedbefore.setter.defprice(self,new_price):-Theheaderandthelistofparameters.Noticehowthenameofthepropertyisusedasthenameofthesetter.Wealsohaveasecondformalparameter(new_price),whichisthenewvaluethatwillbeassignedtothepriceattribute(ifitisvalid).Finally,wehavethebodyofthesetterwherewevalidatetheargumenttocheckifitisapositivefloatandthen,iftheargumentisvalid,weupdatethevalueoftheattribute.Ifthevalueisnotvalid,adescriptivemessageisprinted.Youcanchoosehowtohandleinvalidvaluesaccordingtheneedsofyourprogram.Thisisanexampleoftheuseofthesettermethodwith@property:>>>house=House(50000.0)#Createinstance >>>house.price=45000.0#Updatevalue >>>house.price#Accessvalue 45000.0Noticehowwearenotchangingthesyntax,butnowweareusinganintermediary(thesetter)tovalidatetheargumentbeforeassigningit.Thenewvalue(45000.0)ispassedasanargumenttothesetter:house.price=45000.0Ifwetrytoassignaninvalidvalue,weseethedescriptivemessage.Wecanalsocheckthatthevaluewasnotupdated:>>>house=House(50000.0) >>>house.price=-50 Pleaseenteravalidprice >>>house.price 50000.0💡Tip:Thisprovesthatthesettermethodisworkingasanintermediary.Itisbeingcalled"behindthescenes"whenwetrytoupdatethevalue,sothedescriptivemessageisdisplayedwhenthevalueisnotvalid.🔸DeleterFinally,wehavethedeletermethod:@price.deleter defprice(self): delself._priceNoticethesyntax:@price.deleter-Usedtoindicatethatthisisthedeletermethodforthepriceproperty.Noticethatthislineisverysimilarto@price.setter,butnowwearedefiningthedeletermethod,[email protected](self):-Theheader.Thismethodonlyhasoneformalparameterdefined,self.delself._price-Thebody,wherewedeletetheinstanceattribute.💡Tip:Noticethatthenameofthepropertyis"reused"forallthreemethods.Thisisanexampleoftheuseofthedeletermethodwith@property:#Createinstance >>>house=House(50000.0) #Theinstanceattributeexists >>>house.price 50000.0 #Deletetheinstanceattribute >>>delhouse.price #Theinstanceattributedoesn'texist >>>house.price Traceback(mostrecentcalllast): File"",line1,in house.price File"",line8,inprice returnself._price AttributeError:'House'objecthasnoattribute'_price'Theinstanceattributewasdeletedsuccessfully?.Whenwetrytoaccessitagain,anerroristhrownbecausetheattributedoesn'texistanymore.🔹SomefinalTipsYoudon'tnecessarilyhavetodefineallthreemethodsforeveryproperty.Youcandefineread-onlypropertiesbyonlyincludingagettermethod.Youcouldalsochoosetodefineagetterandsetterwithoutadeleter.Ifyouthinkthatanattributeshouldonlybesetwhentheinstanceiscreatedorthatitshouldonlybemodifiedinternallywithintheclass,youcanomitthesetter.Youcanchoosewhichmethodstoincludedependingonthecontextthatyouareworkingwith.🔸InSummaryYoucandefinepropertieswiththe@propertysyntax,whichismorecompactandreadable.@propertycanbeconsideredthe"pythonic"wayofdefininggetters,setters,anddeleters.Bydefiningproperties,youcanchangetheinternalimplementationofaclasswithoutaffectingtheprogram,soyoucanaddgetters,setters,anddeletersthatactasintermediaries"behindthescenes"toavoidaccessingormodifyingthedatadirectly.Ireallyhopeyoulikedmyarticleandfoundithelpful.TolearnmoreaboutPropertiesandObjectOrientedProgramminginPython,checkoutmyonlinecourse,whichincludes6+hoursofvideolectures,codingexercises,andminiprojects. EstefaniaCassingenaNavone I'madeveloper,writer,[email protected]ñolYouTubechannel. Ifyoureadthisfar,tweettotheauthortoshowthemyoucare.Tweetathanks Learntocodeforfree.freeCodeCamp'sopensourcecurriculumhashelpedmorethan40,000peoplegetjobsasdevelopers.Getstarted



請為這篇文章評分?