How does the @property decorator work in Python? - Stack ...

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

A Python decorator is a function that helps to add some additional functionalities to an already defined function. In Python, everything is an ... Home Public Questions Tags Users Collectives ExploreCollectives FindaJob Jobs Companies Teams StackOverflowforTeams –Collaborateandshareknowledgewithaprivategroup. CreateafreeTeam WhatisTeams? Teams CreatefreeTeam CollectivesonStackOverflow Findcentralized,trustedcontentandcollaboratearoundthetechnologiesyouusemost. Learnmore Teams Q&Aforwork Connectandshareknowledgewithinasinglelocationthatisstructuredandeasytosearch. Learnmore Howdoesthe@propertydecoratorworkinPython? AskQuestion Asked 8years,9monthsago Modified 4daysago Viewed 643ktimes 1210 529 Iwouldliketounderstandhowthebuilt-infunctionpropertyworks.Whatconfusesmeisthatpropertycanalsobeusedasadecorator,butitonlytakesargumentswhenusedasabuilt-infunctionandnotwhenusedasadecorator. Thisexampleisfromthedocumentation: classC: def__init__(self): self._x=None defgetx(self): returnself._x defsetx(self,value): self._x=value defdelx(self): delself._x x=property(getx,setx,delx,"I'mthe'x'property.") property'sargumentsaregetx,setx,delxandadocstring. Inthecodebelowpropertyisusedasadecorator.Theobjectofitisthexfunction,butinthecodeabovethereisnoplaceforanobjectfunctioninthearguments. classC: def__init__(self): self._x=None @property defx(self): """I'mthe'x'property.""" returnself._x @x.setter defx(self,value): self._x=value @x.deleter defx(self): delself._x Howarethex.setterandx.deleterdecoratorscreatedinthiscase? pythonpropertiesdecoratorpython-decoratorspython-internals Share Improvethisquestion Follow editedJan13,2021at23:00 Boris 9,83177goldbadges7575silverbadges7777bronzebadges askedJun26,2013at20:47 ashimashim 22.4k2929goldbadges7070silverbadges9191bronzebadges 8 19 Seealso:HowdoPythonpropertieswork? – MartinThoma Feb3,2015at8:24 3 propertyisactuallyaclass(notafunction),althoughitdoesprobablydoescallthe__init__()methodwhenyoumakeanobject,ofcourse.Usinghelp(property)fromtheterminalisinsightful.helpisalsoaclassforsomereason. – Brōtsyorfuzthrāx Dec8,2016at8:17 2 Ithinkthislinkprovidesagoodexample:[property](journaldev.com/14893/python-property-decorator) – ShengBi Feb7,2019at16:55 4 @Shule2-year-oldthread,butstill:Everythingisaclass.Evenclasses. – Artemis Apr23,2019at20:27 3 Thiswasconfusingtometoo.Ifinallyfoundanarticlethatwasabletobreakitdownforme.Ihopethishelpssomeoneelse.programiz.com/python-programming/propertyI'mnotaffiliatedinanywaywiththesite. – jjwdesign Jun14,2019at17:55  |  Show3morecomments 14Answers 14 Sortedby: Resettodefault Highestscore(default) Datemodified(newestfirst) Datecreated(oldestfirst) 1185 Theproperty()functionreturnsaspecialdescriptorobject: >>>property() Itisthisobjectthathasextramethods: >>>property().getter >>>property().setter >>>property().deleter Theseactasdecoratorstoo.Theyreturnanewpropertyobject: >>>property().getter(None) thatisacopyoftheoldobject,butwithoneofthefunctionsreplaced. Remember,thatthe@decoratorsyntaxisjustsyntacticsugar;thesyntax: @property deffoo(self):returnself._foo reallymeansthesamethingas deffoo(self):returnself._foo foo=property(foo) sofoothefunctionisreplacedbyproperty(foo),[email protected](),whatyouaredoingiscallthatproperty().settermethodIshowedyouabove,whichreturnsanewcopyoftheproperty,butthistimewiththesetterfunctionreplacedwiththedecoratedmethod. Thefollowingsequencealsocreatesafull-onproperty,byusingthosedecoratormethods. Firstwecreatesomefunctionsandapropertyobjectwithjustagetter: >>>defgetter(self):print('Get!') ... >>>defsetter(self,value):print('Setto{!r}!'.format(value)) ... >>>defdeleter(self):print('Delete!') ... >>>prop=property(getter) >>>prop.fgetisgetter True >>>prop.fsetisNone True >>>prop.fdelisNone True Nextweusethe.setter()methodtoaddasetter: >>>prop=prop.setter(setter) >>>prop.fgetisgetter True >>>prop.fsetissetter True >>>prop.fdelisNone True Lastweaddadeleterwiththe.deleter()method: >>>prop=prop.deleter(deleter) >>>prop.fgetisgetter True >>>prop.fsetissetter True >>>prop.fdelisdeleter True Lastbutnotleast,thepropertyobjectactsasadescriptorobject,soithas.__get__(),.__set__()and.__delete__()methodstohookintoinstanceattributegetting,settinganddeleting: >>>classFoo:pass ... >>>prop.__get__(Foo(),Foo) Get! >>>prop.__set__(Foo(),'bar') Setto'bar'! >>>prop.__delete__(Foo()) Delete! TheDescriptorHowtoincludesapurePythonsampleimplementationoftheproperty()type: classProperty: "EmulatePyProperty_Type()inObjects/descrobject.c" def__init__(self,fget=None,fset=None,fdel=None,doc=None): self.fget=fget self.fset=fset self.fdel=fdel ifdocisNoneandfgetisnotNone: doc=fget.__doc__ self.__doc__=doc def__get__(self,obj,objtype=None): ifobjisNone: returnself ifself.fgetisNone: raiseAttributeError("unreadableattribute") returnself.fget(obj) def__set__(self,obj,value): ifself.fsetisNone: raiseAttributeError("can'tsetattribute") self.fset(obj,value) def__delete__(self,obj): ifself.fdelisNone: raiseAttributeError("can'tdeleteattribute") self.fdel(obj) defgetter(self,fget): returntype(self)(fget,self.fset,self.fdel,self.__doc__) defsetter(self,fset): returntype(self)(self.fget,fset,self.fdel,self.__doc__) defdeleter(self,fdel): returntype(self)(self.fget,self.fset,fdel,self.__doc__) Share Improvethisanswer Follow editedOct20,2019at19:02 Boris 9,83177goldbadges7575silverbadges7777bronzebadges answeredJun26,2013at20:54 MartijnPieters♦MartijnPieters 949k260260goldbadges37533753silverbadges31543154bronzebadges 25 13 Verygood.YoucouldaddthefactthatafterFoo.prop=propyoucandoFoo().prop=5;prontFoo().prop;delFoo().propwiththedesiredoutcome. – glglgl Jun27,2013at7:25 13 Methodobjectsarecreatedontheflyandcanreusethesamememorylocationifavailable. – MartijnPieters ♦ Jun12,2014at19:15 1 @MarkusMeskanen:Iratherusetype()asaccessingdunderattributesandmethodsaremeanttobeusedasextensionpointsbythestandardfunctionsandoperators. – MartijnPieters ♦ Mar10,2015at21:46 2 @MarkusMeskanen:becausetheobjectisimmutable,andifyoumutateditinplaceyoucouldnotspecialiseitinasubclass. – MartijnPieters ♦ Jun13,2015at14:25 7 @MarkusMeskanen:seePythonoverridinggetterwithoutsetter;if@human.name.getteralteredthepropertyobjectin-placeratherthanreturnanew,thehuman.nameattributewouldbealtered,changingthebehaviourofthatsuperclass. – MartijnPieters ♦ Jun13,2015at14:33  |  Show20morecomments 293 Documentationsaysit'sjustashortcutforcreatingreadonlyproperties.So @property defx(self): returnself._x isequivalentto defgetx(self): returnself._x x=property(getx) Share Improvethisanswer Follow editedJul15,2016at20:45 λuser 86688silverbadges1414bronzebadges answeredJun26,2013at20:52 J0HNJ0HN 24.9k55goldbadges4747silverbadges8484bronzebadges 2 55 Thefullcontext(most-upvotedanswer)isgood,butthisanswerwaspracticallyusefulforfiguringoutwhysomeoneelsehadused@propertyasadecoratorintheirclass. – ijoseph Apr16,2019at23:23 4 "...shortcutforcreatingreadonlyproperties.".Themilliondolahanswer! – Saptadeep Oct27,2021at18:00 Addacomment  |  153 Hereisaminimalexampleofhow@propertycanbeimplemented: classThing: def__init__(self,my_word): self._word=my_word @property defword(self): returnself._word >>>print(Thing('ok').word) 'ok' Otherwisewordremainsamethodinsteadofaproperty. classThing: def__init__(self,my_word): self._word=my_word defword(self): returnself._word >>>print(Thing('ok').word()) 'ok' Share Improvethisanswer Follow answeredFeb15,2017at0:46 AlexGAlexG 9,84466goldbadges5858silverbadges6868bronzebadges 4 1 Howwouldthisexamplelookiftheword()function/propertyneededtobedefinedininit? – J.J Apr9,2017at9:51 14 CansomeonepleaseexplainwhyIwouldcreateapropertydecoratorhere,insteadofjusthavingself.word=my_word--whichwouldthenworkthesamewayprint(Thing('ok').word)='ok' – SilverSlash Jun9,2017at4:41 1 @SilverSlashThisisjustasimpleexample,arealuse-casewouldinvolveamorecomplicatedmethod – AlexG Jun9,2017at16:22 canyoupleaseexplainme,howprintingThing('ok').wordcallsthefunctioninternallyatruntime? – Vicrobot Dec27,2019at13:35 Addacomment  |  90 Thefirstpartissimple: @property defx(self):... isthesameas defx(self):... x=property(x) which,inturn,isthesimplifiedsyntaxforcreatingapropertywithjustagetter. Thenextstepwouldbetoextendthispropertywithasetterandadeleter.Andthishappenswiththeappropriatemethods: @x.setter defx(self,value):... returnsanewpropertywhichinheritseverythingfromtheoldxplusthegivensetter. x.deleterworksthesameway. Share Improvethisanswer Follow answeredJun26,2013at20:53 glglglglglgl 84.6k1111goldbadges137137silverbadges208208bronzebadges Addacomment  |  84 Belowisanotherexampleonhow@propertycanhelpwhenonehastorefactorcodewhichistakenfromhere(Ionlysummarizeitbelow): ImagineyoucreatedaclassMoneylikethis: classMoney: def__init__(self,dollars,cents): self.dollars=dollars self.cents=cents andanusercreatesalibrarydependingonthisclasswherehe/sheusese.g. money=Money(27,12) print("Ihave{}dollarand{}cents.".format(money.dollars,money.cents)) #printsIhave27dollarand12cents. Nowlet'ssupposeyoudecidetochangeyourMoneyclassandgetridofthedollarsandcentsattributesbutinsteaddecidetoonlytrackthetotalamountofcents: classMoney: def__init__(self,dollars,cents): self.total_cents=dollars*100+cents Iftheabovementionedusernowtriestorunhis/herlibraryasbefore money=Money(27,12) print("Ihave{}dollarand{}cents.".format(money.dollars,money.cents)) itwillresultinanerror AttributeError:'Money'objecthasnoattribute'dollars' ThatmeansthatnoweveryonewhoreliesonyouroriginalMoneyclasswouldhavetochangealllinesofcodewheredollarsandcentsareusedwhichcanbeverypainful...So,howcouldthisbeavoided?Byusing@property! Thatishow: classMoney: def__init__(self,dollars,cents): self.total_cents=dollars*100+cents #Getterandsetterfordollars... @property defdollars(self): returnself.total_cents//100 @dollars.setter defdollars(self,new_dollars): self.total_cents=100*new_dollars+self.cents #Andthegetterandsetterforcents. @property defcents(self): returnself.total_cents%100 @cents.setter defcents(self,new_cents): self.total_cents=100*self.dollars+new_cents whenwenowcallfromourlibrary money=Money(27,12) print("Ihave{}dollarand{}cents.".format(money.dollars,money.cents)) #printsIhave27dollarand12cents. itwillworkasexpectedandwedidnothavetochangeasinglelineofcodeinourlibrary!Infact,wewouldnotevenhavetoknowthatthelibrarywedependonchanged. Alsothesetterworksfine: money.dollars+=2 print("Ihave{}dollarand{}cents.".format(money.dollars,money.cents)) #printsIhave29dollarand12cents. money.cents+=10 print("Ihave{}dollarand{}cents.".format(money.dollars,money.cents)) #printsIhave29dollarand22cents. Youcanuse@propertyalsoinabstractclasses;Igiveaminimalexamplehere. Share Improvethisanswer Follow editedSep16,2019at21:42 answeredSep23,2018at11:58 ClebCleb 22.5k1818goldbadges100100silverbadges139139bronzebadges 4 3 yoursummaryisverygood,theexamplethatwebsitetakesisalittlebitstrange..Abeginnerwouldask..whycan'twejuststicktotheself.dollar=dollars?wehavedonesomuchwith@property,butitseemsnoextractfunctionalityisadded. – ShengBi Feb7,2019at16:39 4 @ShengBi:Donotfocusthatmuchontheactualexamplebutmoreontheunderlyingprinciple:If-forwhateverreason-youhavetorefactorcode,youcandosowithoutaffectinganyoneother'scode. – Cleb Feb7,2019at16:44 1 @clebyoudarealmvp.Everybodyelseusesthatgettersetterexamplelikethisone,programiz.com/python-programming/property.Butyouaretheonlyonethatactuallyexplainswhywewantproperty.It'sbecausewhenwewritessomethinguponwhichalotofpeoplearegoingtobuild,wewanttobeabletomodifythebaseclasseswithoutnorealimpactonhowthesuccessorsuseorbuilduponourwork,implementationwise. – ChenLizi Apr7,2021at0:28 1 @ClebIsuredid!:) – ChenLizi Apr7,2021at17:27 Addacomment  |  58 Thisfollowing: classC(object): def__init__(self): self._x=None @property defx(self): """I'mthe'x'property.""" returnself._x @x.setter defx(self,value): self._x=value @x.deleter defx(self): delself._x Isthesameas: classC(object): def__init__(self): self._x=None def_x_get(self): returnself._x def_x_set(self,value): self._x=value def_x_del(self): delself._x x=property(_x_get,_x_set,_x_del, "I'mthe'x'property.") Isthesameas: classC(object): def__init__(self): self._x=None def_x_get(self): returnself._x def_x_set(self,value): self._x=value def_x_del(self): delself._x x=property(_x_get,doc="I'mthe'x'property.") x=x.setter(_x_set) x=x.deleter(_x_del) Isthesameas: classC(object): def__init__(self): self._x=None def_x_get(self): returnself._x x=property(_x_get,doc="I'mthe'x'property.") def_x_set(self,value): self._x=value x=x.setter(_x_set) def_x_del(self): delself._x x=x.deleter(_x_del) Whichisthesameas: classC(object): def__init__(self): self._x=None @property defx(self): """I'mthe'x'property.""" returnself._x @x.setter defx(self,value): self._x=value @x.deleter defx(self): delself._x Share Improvethisanswer Follow answeredMay24,2017at18:38 BimoBimo 5,01311goldbadge3131silverbadges4848bronzebadges 2 5 Thefirstandlastcodeexamplesarethesame(verbatim). – AdomasBaliuka Aug15,2019at2:13 2 Ithinkit'sintentional.Eitherway,thiswasthemostusefulexampletomebecauseIcangrokmeaningfromtheseexamples.Thanks@BillMoore – Jérémie Jun14,2020at16:20 Addacomment  |  36 Let'sstartwithPythondecorators. APythondecoratorisafunctionthathelpstoaddsomeadditionalfunctionalitiestoanalreadydefinedfunction. InPython,everythingisanobject.FunctionsinPythonarefirst-classobjectswhichmeansthattheycanbereferencedbyavariable,addedinthelists,passedasargumentstoanotherfunction,etc. Considerthefollowingcodesnippet. defdecorator_func(fun): defwrapper_func(): print("Wrapperfunctionstarted") fun() print("Givenfunctiondecorated") #Wrapperfunctionaddsomethingtothepassedfunctionanddecorator #returnsthewrapperfunction returnwrapper_func defsay_bye(): print("bye!!") say_bye=decorator_func(say_bye) say_bye() #Output: #Wrapperfunctionstarted #bye!! #Givenfunctiondecorated Here,wecansaythatthedecoratorfunctionmodifiedoursay_byefunctionandaddedsomeextralinesofcodetoit. Pythonsyntaxfordecorator defdecorator_func(fun): defwrapper_func(): print("Wrapperfunctionstarted") fun() print("Givenfunctiondecorated") #Wrapperfunctionaddsomethingtothepassedfunctionanddecorator #returnsthewrapperfunction returnwrapper_func @decorator_func defsay_bye(): print("bye!!") say_bye() Let'sgothrougheverythingwithacasescenario.Butbeforethat,let'stalkaboutsomeOOPprinciples. Gettersandsettersareusedinmanyobject-orientedprogramminglanguagestoensuretheprincipleofdataencapsulation(whichisseenasthebundlingofdatawiththemethodsthatoperateonthesedata.) Thesemethodsare,ofcourse,thegetterforretrievingthedataandthesetterforchangingthedata. Accordingtothisprinciple,theattributesofaclassaremadeprivatetohideandprotectthemfromothercode. Yup,@propertyisbasicallyapythonicwaytousegettersandsetters. Pythonhasagreatconceptcalledpropertywhichmakesthelifeofanobject-orientedprogrammermuchsimpler. LetusassumethatyoudecidetomakeaclassthatcouldstorethetemperatureindegreesCelsius. classCelsius: def__init__(self,temperature=0): self.set_temperature(temperature) defto_fahrenheit(self): return(self.get_temperature()*1.8)+32 defget_temperature(self): returnself._temperature defset_temperature(self,value): ifvalue1000: self.__x=1000 else: self.__x=x Thisisgreat,isn'tit:Youcanstartwiththesimplestimplementationimaginable,andyouarefreetolatermigratetoapropertyversionwithouthavingtochangetheinterface!Sopropertiesarenotjustareplacementforgettersandsetters! YoucancheckthisImplementationhere Share Improvethisanswer Follow editedJul23,2021at9:25 Useless 59.1k55goldbadges7979silverbadges123123bronzebadges answeredSep17,2018at0:01 DivyanshuRawatDivyanshuRawat 3,47111goldbadge3232silverbadges4141bronzebadges 7 7 YourCelsiusclassisgoingtoinfinitelyrecursewhensetting(whichmeansuponinstantiation). – TedPetrou Sep23,2018at12:25 1 @TedPetrouIDidn'tgetyou?Howitwillinfinitelyrecursewhensetting? – DivyanshuRawat Sep23,2018at12:37 1 Peopleareaskinghowdoesitworknotwhyitworks?@ShengBi – DivyanshuRawat Feb7,2019at17:53 1 Itisjustacomment,mypersonalopinion.Youranswercouldbereallygood.soleaveit. – ShengBi Feb10,2019at1:14 2 comparedtothetopvotedanswers,thisoneisdesignedforhumans;thanks. – Info5ek May18,2020at0:06  |  Show2morecomments 28 Ireadallthepostshereandrealizedthatwemayneedareallifeexample.Why,actually,wehave@property? So,consideraFlaskappwhereyouuseauthenticationsystem. YoudeclareamodelUserinmodels.py: classUser(UserMixin,db.Model): __tablename__='users' id=db.Column(db.Integer,primary_key=True) email=db.Column(db.String(64),unique=True,index=True) username=db.Column(db.String(64),unique=True,index=True) password_hash=db.Column(db.String(128)) ... @property defpassword(self): raiseAttributeError('passwordisnotareadableattribute') @password.setter defpassword(self,password): self.password_hash=generate_password_hash(password) defverify_password(self,password): returncheck_password_hash(self.password_hash,password) Inthiscodewe've"hidden"attributepasswordbyusing@propertywhichtriggersAttributeErrorassertionwhenyoutrytoaccessitdirectly,whileweused@property.settertosettheactualinstancevariablepassword_hash. Nowinauth/views.pywecaninstantiateaUserwith: ... @auth.route('/register',methods=['GET','POST']) defregister(): form=RegisterForm() ifform.validate_on_submit(): user=User(email=form.email.data, username=form.username.data, password=form.password.data) db.session.add(user) db.session.commit() ... Noticeattributepasswordthatcomesfromaregistrationformwhenauserfillstheform.PasswordconfirmationhappensonthefrontendwithEqualTo('password',message='Passwordsmustmatch')(incaseifyouarewondering,butit'sadifferenttopicrelatedFlaskforms). Ihopethisexamplewillbeuseful Share Improvethisanswer Follow editedSep10,2019at15:24 answeredMar23,2018at14:47 LeoSkhrnkvLeoSkhrnkv 1,2551515silverbadges2525bronzebadges Addacomment  |  18 ThispointisbeenclearedbymanypeopleuptherebuthereisadirectpointwhichIwassearching. ThisiswhatIfeelisimportanttostartwiththe@propertydecorator. eg:- classUtilityMixin(): @property defget_config(self): return"Thisisproperty" Thecallingoffunction"get_config()"willworklikethis. util=UtilityMixin() print(util.get_config) IfyounoticeIhavenotused"()"bracketsforcallingthefunction.ThisisthebasicthingwhichIwassearchingforthe@propertydecorator.Sothatyoucanuseyourfunctionjustlikeavariable. Share Improvethisanswer Follow editedNov26,2018at6:39 answeredNov9,2018at13:00 DevendraBhatDevendraBhat 1,04111goldbadge1313silverbadges1919bronzebadges 0 Addacomment  |  8 propertyisaclassbehind@propertydecorator. Youcanalwayscheckthis: print(property)# Irewrotetheexamplefromhelp(property)toshowthatthe@propertysyntax classC: def__init__(self): self._x=None @property defx(self): returnself._x @x.setter defx(self,value): self._x=value @x.deleter defx(self): delself._x c=C() c.x="a" print(c.x) isfunctionallyidenticaltoproperty()syntax: classC: def__init__(self): self._x=None defg(self): returnself._x defs(self,v): self._x=v defd(self): delself._x prop=property(g,s,d) c=C() c.x="a" print(c.x) Thereisnodifferencehowweusethepropertyasyoucansee. Toanswerthequestion@propertydecoratorisimplementedviapropertyclass. So,thequestionistoexplainthepropertyclassabit. Thisline: prop=property(g,s,d) Wastheinitialization.Wecanrewriteitlikethis: prop=property(fget=g,fset=s,fdel=d) Themeaningoffget,fsetandfdel: |fget |functiontobeusedforgettinganattributevalue |fset |functiontobeusedforsettinganattributevalue |fdel |functiontobeusedfordel'inganattribute |doc |docstring Thenextimageshowsthetripletswehave,fromtheclassproperty: __get__,__set__,and__delete__aretheretobeoverridden.ThisistheimplementationofthedescriptorpatterninPython. Ingeneral,adescriptorisanobjectattributewith“bindingbehavior”,onewhoseattributeaccesshasbeenoverriddenbymethodsinthedescriptorprotocol. Wecanalsousepropertysetter,getteranddeletermethodstobindthefunctiontoproperty.Checkthenextexample.Themethods2oftheclassCwillsetthepropertydoubled. classC: def__init__(self): self._x=None defg(self): returnself._x defs(self,x): self._x=x defd(self): delself._x defs2(self,x): self._x=x+x x=property(g) x=x.setter(s) x=x.deleter(d) c=C() c.x="a" print(c.x)#outputs"a" C.x=property(C.g,C.s2) C.x=C.x.deleter(C.d) c2=C() c2.x="a" print(c2.x)#outputs"aa" Share Improvethisanswer Follow editedMay26,2019at21:10 answeredMay26,2019at16:27 prostiprosti 34k99goldbadges157157silverbadges139139bronzebadges Addacomment  |  8 Thebestexplanationcanbefoundhere: Python@PropertyExplained–HowtoUseandWhen?(FullExamples) bySelvaPrabhakaran|PostedonNovember5,2018 IthelpedmeunderstandWHYnotonlyHOW. https://www.machinelearningplus.com/python/python-property/ Share Improvethisanswer Follow editedFeb25,2020at3:50 answeredFeb22,2020at1:28 VictorWangVictorWang 57988silverbadges1818bronzebadges 1 Thisisthebestsourceasofnow – thanos.a Mar19at3:00 Addacomment  |  5 Adecoratorisafunctionthattakesafunctionasanargumentandreturnsaclosure.Theclosureisasetofinnerfunctionsandfreevariables.Theinnerfunctionisclosingoverthefreevariableandthatiswhyitiscalled'closure'.Afreevariableisavariablethatisoutsidetheinnerfunctionandpassedintotheinnerviadocorator. Asthenamesays,decoratorisdecoratingthereceivedfunction. functiondecorator(undecorated_func): print("callingdecoratorfunc") inner(): print("Iaminsideinner") returnundecorated_func returninner thisisasimpledecoratorfunction.Itreceived"undecorated_func"andpassedittoinner()asafreevariable,inner()printed"Iaminsideinner"andreturnedundecorated_func.Whenwecalldecorator(undecorated_func),itisreturningtheinner.Hereisthekey,indecoratorswearenamingtheinnerfunctionasthenameofthefunctionthatwepassed. undecorated_function=decorator(undecorated_func) nowinnerfunctioniscalled"undecorated_func".Sinceinnerisnownamedas"undecorated_func",wepassed"undecorated_func"tothedecoratorandwereturned"undecorated_func"plusprintedout"Iaminsideinner".sothisprintstatementdecoratedour"undecorated_func". nowlet'sdefineaclasswithapropertydecorator: classPerson: def__init__(self,name): self._name=name @property defname(self): returnself._name @name.setter defname(self.value): self._name=value whenwedecoratedname()with@property(),thisiswhathappened: name=property(name)#Person.__dict__youllseename firstargumentofproperty()isgetter.thisiswhathappenedintheseconddecoration: name=name.setter(name) AsImentionedabove,thedecoratorreturnstheinnerfunction,andwenametheinnerfunctionwiththenameofthefunctionthatwepassed. Hereisanimportantthingtobeawareof."name"isimmutable.inthefirstdecorationwegotthis: name=property(name) inthesecondonewegotthis name=name.setter(name) Wearenotmodifyingnameobj.Intheseconddecoration,pythonseesthatthisispropertyobjectanditalreadyhadgetter.Sopythoncreatesanew"name"object,addsthe"fget"fromthefirstobjandthensetsthe"fset". Share Improvethisanswer Follow editedMar19at2:47 answeredNov30,2020at21:02 YilmazYilmaz 12.2k77goldbadges6464silverbadges9999bronzebadges 2 Youranswerhasalotoftyposandsytaxmistakesthatpreventedmefromreadingit. – thanos.a Mar19at2:44 @thanos.aIamsosorryaboutit:)IdideditedsometyposbutIdonotseeanysyntaxerror – Yilmaz Mar19at2:48 Addacomment  |  1 Apropertycanbedeclaredintwoways. Creatingthegetter,settermethodsforanattributeandthenpassingtheseasargumenttopropertyfunction Usingthe@propertydecorator. YoucanhavealookatfewexamplesIhavewrittenaboutpropertiesinpython. Share Improvethisanswer Follow answeredJul13,2017at9:20 nvdnvd 38933silverbadges22bronzebadges 1 canyouupdatedyouranswersayingthatpropertyisaclasssoIcanupvote. – prosti May26,2019at21:43 Addacomment  |  0 Hereisanotherexample: ## ##PythonPropertiesExample ## classGetterSetterExample(object): ##Setthedefaultvalueforx(wereferenceitusingself.x,setavalueusingself.x=value) __x=None ## ##OnClassInitialization-dosomething...ifwewant.. ## def__init__(self): ##Setavalueto__xthroughthegetter/setter...Since__xisdefinedabove,thisdoesn'tneedtobeset... self.x=1234 returnNone ## ##Definexasaproperty,ieagetter-Allgettersshouldhaveadefaultvaluearg,soIaddedit-itwillnotbepassedinwhensettingavalue,soyouneedtosetthedefaultheresoitwillbeused.. ## @property defx(self,_default=None): ##Iaddedanoptionaldefaultvalueargumentasallgettersshouldhavethis-setittothedefaultvalueyouwanttoreturn... _value=(self.__x,_default)[self.__x==None] ##Debugging-soyoucanseetheorderthecallsaremade... print('[TestClass]Getx='+str(_value)) ##Returnthevalue-weareagetterafterall... return_value ## ##Definethesetterfunctionforx... ## @x.setter defx(self,_value=None): ##Debugging-soyoucanseetheorderthecallsaremade... print('[TestClass]Setx='+str(_value)) ##Thisistoshowthesetterfunctionworks....Ifthevalueisabove0,setittoanegativevalue...otherwisekeepitasis(0istheonlynon-negativenumber,itcan'tbenegativeorpositiveanyway) if(_value>0): self.__x=-_value else: self.__x=_value ## ##Definethedeleterfunctionforx... ## @x.deleter defx(self): ##Unloadtheassignment/dataforx if(self.__x!=None): delself.__x ## ##ToString/OutputFunctionfortheclass-thiswillshowthepropertyvalueforeachpropertyweadd... ## def__str__(self): ##Outputthexpropertydata... print('[x]'+str(self.x)) ##Returnanewline-technicallyweshouldreturnastringsoitcanbeprintedwherewewantit,insteadofprintedearlyif_data=str(C())isused.... return'\n' ## ## ## _test=GetterSetterExample() print(_test) ##Forsomereasonthedeleterisn'tbeingcalled... del_test.x Basically,thesameastheC(object)exampleexceptI'musingxinstead...Ialsodon'tinitializein__init-...well..Ido,butitcanberemovedbecause__xisdefinedaspartoftheclass.... Theoutputis: [TestClass]Setx=1234 [TestClass]Getx=-1234 [x]-1234 andifIcommentouttheself.x=1234ininitthentheoutputis: [TestClass]Getx=None [x]None andifIsetthe_default=Noneto_default=0inthegetterfunction(asallgettersshouldhaveadefaultvaluebutitisn'tpassedinbythepropertyvaluesfromwhatI'veseensoyoucandefineithere,anditactuallyisn'tbadbecauseyoucandefinethedefaultonceanduseiteverywhere)ie:defx(self,_default=0): [TestClass]Getx=0 [x]0 Note:Thegetterlogicistherejusttohavethevaluebemanipulatedbyittoensureitismanipulatedbyit-thesamefortheprintstatements... Note:I'musedtoLuaandbeingabletodynamicallycreate10+helperswhenIcallasinglefunctionandImadesomethingsimilarforPythonwithoutusingpropertiesanditworkstoadegree,but,eventhoughthefunctionsarebeingcreatedbeforebeingused,therearestillissuesattimeswiththembeingcalledpriortobeingcreatedwhichisstrangeasitisn'tcodedthatway...IprefertheflexibilityofLuameta-tablesandthefactIcanuseactualsetters/gettersinsteadofessentiallydirectlyaccessingavariable...IdolikehowquicklysomethingscanbebuiltwithPythonthough-forinstanceguiprograms.althoughoneIamdesigningmaynotbepossiblewithoutalotofadditionallibraries-ifIcodeitinAutoHotkeyIcandirectlyaccessthedllcallsIneed,andthesamecanbedoneinJava,C#,C++,andmore-maybeIhaven'tfoundtherightthingyetbutforthatprojectImayswitchfromPython.. Note:Thecodeoutputinthisforumisbroken-Ihadtoaddspacestothefirstpartofthecodeforittowork-whencopy/pastingensureyouconvertallspacestotabs....IusetabsforPythonbecauseinafilewhichis10,000linesthefilesizecanbe512KBto1MBwithspacesand100to200KBwithtabswhichequatestoamassivedifferenceforfilesize,andreductioninprocessingtime... Tabscanalsobeadjustedperuser-soifyouprefer2spaceswidth,4,8orwhateveryoucandoitmeaningitisthoughtfulfordeveloperswitheye-sightdeficits. Note:Allofthefunctionsdefinedintheclassaren'tindentedproperlybecauseofabugintheforumsoftware-ensureyouindentitifyoucopy/paste Share Improvethisanswer Follow answeredAug7,2018at11:08 AcecoolAcecool 62488silverbadges1212bronzebadges Addacomment  |  YourAnswer ThanksforcontributingananswertoStackOverflow!Pleasebesuretoanswerthequestion.Providedetailsandshareyourresearch!Butavoid…Askingforhelp,clarification,orrespondingtootheranswers.Makingstatementsbasedonopinion;backthemupwithreferencesorpersonalexperience.Tolearnmore,seeourtipsonwritinggreatanswers. Draftsaved Draftdiscarded Signuporlogin SignupusingGoogle SignupusingFacebook SignupusingEmailandPassword Submit Postasaguest Name Email Required,butnevershown PostYourAnswer Discard Byclicking“PostYourAnswer”,youagreetoourtermsofservice,privacypolicyandcookiepolicy Nottheansweryou'relookingfor?Browseotherquestionstaggedpythonpropertiesdecoratorpython-decoratorspython-internalsoraskyourownquestion. TheOverflowBlog AIandnanotechnologyareworkingtogethertosolvereal-worldproblems GettingthroughaSOC2auditwithyournervesintact FeaturedonMeta WhatgoesintositesponsorshipsonSE? StackExchangeQ&AaccesswillnotberestrictedinRussia NewUserExperience:DeepDiveintoourResearchontheStagingGround–How... AskWizardforNewUsersFeatureTestisnowLive Linked 2 RecursionError:maximumrecursiondepthexceededpythonpropertygettersetter 0 CallingaclassmemberfunctiongivesTypeError -1 whatiswrongwiththispropertydecorator(python) -3 Howcancallclassmethodwithoutbracket`()`? 1 Pythonpropertydetail 0 Whyisn'tthereanamingconflictindecoratingchainingcode? 1 Whydoesthepropertybuiltinworkinconjunctionwithclassesbutnotoutsideofthem? -1 Whatdoesthepropertypythonbuiltindo? 0 Wheredoespython@setterreceiveitsargumentfromwhencalledfromwithinclass? -3 Explaingetterandsetterinpythoninsimplewords Seemorelinkedquestions Related 3246 Howtocopyfiles? 11905 Whatdoesthe"yield"keyworddo? 5128 HowcanIsafelycreateanesteddirectory? 7201 DoesPythonhaveaternaryconditionaloperator? 3504 HowtogetthecurrenttimeinPython 3250 HowdoIconcatenatetwolistsinPython? 2468 HowtoupgradeallPythonpackageswithpip 3591 DoesPythonhaveastring'contains'substringmethod? 2865 HowtodeleteafileorfolderinPython? HotNetworkQuestions HowdoyouexplainCanada'sTrudeau'spower-sharingagreementtoafive-year-old(American)? ConvertDateformattoinsertintoMySQLdatabase InterpretationofasubtoureliminationconstraintintheTSP HowDoesOrbitalWarfareWork? EnigmarchDay1:Initial Whatisagoodsoftwaretomaketechincaland/orschematicillustrationsaboutspace/orbitaldynamicstopics? WhatcanweeatinthelateCretaceous? TikZarcwithextremeangle WhydoesahypersonicmissileneedtocruiseEarthatlowaltitudebeforehittingitsmark? Whydoesn'ttheUSsendairplanestoUkraine,whenRussianssentMIGstoVietnamduringVietnamwar? Iturnedabreakeroff,andnowthesecurityalarmsystemwon’tstopbeeping problemswritingequation IfplayerAisincheckbuthasamovewhichwillcheckmateplayerBwithoutexitingcheck,isthatmovelegal? Howdoeslicensingsoftwarenotimplyownership?Don'tIownaWindowsoperatingsystemonceIpayforit? NFA:Howdoesitfunctionwithempty-stringmoves? Haskellcomparingtwolists'lengthsbutoneofthemisinfinite? Howtoselectallcurvesonoroutsidearegion? Creatingalistofconditions WhydoAirForceplanesregularlyflyincircles? Sandboxoverflow WhatwouldUkrainegainbydisclosingintelligenceinformationaboutPutinassassinationplans? WeirdpowerlinesforS-100,whyno5V? Couldvideosbeauthenticatedusingprivateandpublickeys? RecreateMinecraft'slighting morehotquestions Questionfeed SubscribetoRSS Questionfeed TosubscribetothisRSSfeed,copyandpastethisURLintoyourRSSreader. lang-py Yourprivacy Byclicking“Acceptallcookies”,youagreeStackExchangecanstorecookiesonyourdeviceanddiscloseinformationinaccordancewithourCookiePolicy. Acceptallcookies Customizesettings  



請為這篇文章評分?