Methods - Python Like You Mean It

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

A class method is similar to an instance method, but it has a class object passed as its first argument. Recall that, when an instance method is called from an ... PythonLikeYouMeanIt 1.4 TableofContents: PythonLikeYouMeanIt Module1:GettingStartedwithPython Module2:TheEssentialsofPython Module2:Problems Module3:TheEssentialsofNumPy Module3:Problems Module4:ObjectOrientedProgramming IntroductiontoObjectOrientedProgramming DefiningaNewClassofObject InstancesofaClass ABriefSummaryofTermsandConcepts Methods InstanceMethods TheselfArgument ClassMethods StaticMethods ReadingComprehensionSolutions ApplicationsofObjectOrientedProgramming SpecialMethods Inheritance Module5:OddsandEnds Changelog PythonLikeYouMeanIt » Module4:ObjectOrientedProgramming» Methods Viewpagesource Methods Recallthatamethodisanattributeofaclassthatisafunction.Forexample,“append”isamethodthatisdefinedforthelistclassand“capitalize”isamethodofthestr(string)class. #createaninstanceofthe`list`class/type #andinvoketheinstancemethod`append` >>>a=[1,2,3] >>>a.append(-1) >>>a [1,2,3,-1] #createaninstanceofthe`str`class/type #andinvoketheinstancemethod`capitalize` >>>b="moo" >>>b.capitalize() 'Moo' Herewewillencounterthreevarietiesofmethods: instancemethods classmethods staticmethods whosedifferencesarerelativelyminorbutareimportanttounderstand.Thefunctions“append”and“capitalize”arebothexamplesofinstancemethods,specifically,astheyaredesignedtobeinvokedbyaparticularlistinstanceandstringinstance,respectively. Wehavealreadyworkedwiththeinstancemethod__init__,whichisspecialinthatitisreservedbyPythontobeexecutedwheneverclass-initializationisinvoked.Similarly,thespecialinstancemethod__add__informshowanobjectinteractswiththe+operator.Forexample,float.__add__specifiesthat+willsumthevaluesoffloatinstances,whereaslist.__add__specifiesthat+willconcatenatelistinstancestogether.Wewillconcludeourdiscussionof methodsbysurveyinganumberofthesespecialmethods-theywillgreatlybolsterourabilitytodefineconvenient,user-friendlyclasses. InstanceMethods Aninstancemethodisdefinedwheneverafunctiondefinitionisspecifiedwithinthebodyofaclass.Thismayseemtrivialbutthereisstillasignificantnuancethatmustbeclearedup,whichisthat‘self’isthedefactofirst-argumentforanyinstancemethod.Thisissomethingthatweencounteredwhenworkingwith__init__.Let’sproceednaivelysothatwewillhitaverycommonerror,whichwillbringthismattertolight.Webeginbycreatingaclasswithaninstancemethodthat simplyacceptsoneargumentandthenreturnsthatargumentunchanged: classDummy: deffunc(x): """Aninstancemethodthatreturns`x`unchanged. Thisisabadversionofthisinstancemethod!""" returnx WecancallthismethodfromtheclassobjectDummyitself,anditwillbehaveas-expected: >>>Dummy.func(2) 2 butsomethingstrangehappenswhenwetrytocallfuncfromaninstanceofDummy: #calling`func`fromaninstanceof`Dummy`produces #anunexpectederror >>>inst=Dummy() >>>inst.func(2) TypeError:func()takes1positionalargumentbut2weregiven Atfirstglance,thiserrormessagedoesn’tseemtomakeanysense.Itisindeedtruethatfunconlyacceptsoneargument-wespecifiedthatitshouldaccepttheargumentxinitsfunctiondefinition.Howisitthatinst.func(2)specifiestwoarguments?Itseemslikewearesolelypassing2toourmethod.Hereinliesanextremelyimportantdetail: Important! Whenyoucallaninstancemethod(e.g.func)fromaninstanceobject(e.g.inst),Pythonautomaticallypassesthatinstanceobjectasthefirstargument,inadditiontoanyotherargumentsthatwerepassedinbytheuser. Soaccordingtothis,instisbeingpassedastheargumentxandweareattemptingtopass2asasecondargumenttothemethod;thisexplainstheerrormessagecomplainingaboutpassingfunctwoarguments.Bythislogicweshouldbeabletocalla.func()andseethatinstisbeingpassedastheargumentx-recallthatfuncisdefinedtosimplyreturnxunchanged.Let’sconfirmthis: #verifyingthat`inst`isbeingpassedasthefirstargument #oftheinstance-method`func` #notethememoryaddressoftheDummy-instance`inst` >>>inst <__main__.dummyat0x284f0008da0> #`inst.func()`automaticallyreceives`inst`asthe #inputargument,whichisthenreturnedunchanged >>>inst.func() <__main__.dummyat0x284f0008da0> #`inst`isindeedbeingpassedto,and #returnedby,`func` >>>out=inst.func() >>>instisout True Notethatthis“underthehood”behavioronlyoccurswhenthemethodisbeingcalledfromaninstance;thisiswhywedidn’tfacethisissuewheninvokingfuncfromDummy-Dummyisaclassobject,notaninstance.Thus,inst.func()isequivalenttoDummy.func(inst): >>>out=Dummy.func(inst) >>>outisinst True Initscurrentform,thereisnowayforustopassanargumenttofuncwhenwearecallingitfromaninstanceofDummy.Tosolvethisissue,wewillrefactorourdefinitionoffunctoanticipatethepassingoftheinstanceobjectasthefirstargument. TheselfArgument WewillwanttodefineourinstancemethodsinawaythatanticipatesthatPythonwillautomaticallypassaninstanceobjectasthefirstargument.Thusifwewantourmethodtoaccept\(N\)externalargument,weshoulddefineitssignaturetohave\(N+1\)arguments,withtheunderstandingthatPythonwillpasstheinstanceobjectasthefirstargument.Theacceptedconventionistocallthisfirstargumentself.Thereisnosignificancetothisnamebeyonditbeingthe widely-adoptedconventionamongPythonusers;“self”ismeanttoindicatethattheinstanceobjectispassingitselfasthefirstargumentofthemethod.Considerthefollowingexample: #demonstratetheuseof`self`ininstancearguments classNumber: def__init__(self,value): self.value=value defadd(self,new_value): returnself.value+new_value #calls__init__,settingself.value=4.0 >>>x=Number(4.0) #`x`getspassedto`self` >>>x.add(2.0) 6.0 #Callingtheinstancemethodfromtheclassobject. #Wemustexplicitlypassanobjectto`self` >>>Number.add(x,2.0) 6.0 Notetheutilityofhavingselfbeautomaticallypassedinasanargumenttoboth__init__andadd.Aninstancemethodismeanttohaveaccesstotheinstanceobjectthatiscallingit-whenyoucallcapitalizefromastringinstance,itisobviousthatyouwanttocapitalizethatspecificstring.ItwouldbetediousandredundantifPythondidnotmanagethatautomatically. Next,wewillseethatwecanalsodefineclass-methods,whichautomaticallyhaveclassobjectsgetpassedastheirfirstarguments,andstaticmethods,whichdonothaveanyobjectspassedtothemunderthehood. ReadingComprehension:InvokingInstanceMethods RewriteDummysothatitsinstancemethodfuncacceptstwoarguments:theinstanceobjectthatPythonautomaticallypassesandtheargumentx,whichwewantfunctoreturnunchanged.CreateaninstanceofDummyandcallfuncfromthisinstanceandpassitthestring"hi",whatwillbereturned?WhatwillhappenifyoutrytocallDummy.func("hi")?Why?HowcanwemodifythiscallfromDummyitselfsothatthemethodwillworkasdesired? ClassMethods Aclassmethodissimilartoaninstancemethod,butithasaclassobjectpassedasitsfirstargument.Recallthat,whenaninstancemethodiscalledfromaninstanceobject,thatinstanceobjectisautomaticallypassedasthefirstargumenttothemethod.Bycontrast,whenaclassmethodiscalledfromaeitheraclassobjectoraninstanceobject,theclassobjectisautomaticallypassedasthefirstargumenttothemethod.Insteadofcallingthisfirstargumentself,theconvention istonameitcls. Todefineaclassmethodyoumustdecoratethemethoddefinitionwithaspecialbuilt-indecoratorclassmethod.Wehavenotdiscusseddecorators.Sufficeittoknowthatthissimply“tags”themethod,sothatPythonknowstotreatitlikeaclassmethodinsteadofaninstancemethod.Thefollowingdemonstratesthisdecorationprocess: classDummy: @classmethod defclass_func(cls): """Aclassmethoddefinedtosimply return`cls`unchanged""" returncls #`Dummy`getspassedas`cls`automatically. #Wedefined`class_func`toreturn`cls`unchanged >>>Dummy.class_func() __main__.Dummy #`Dummy.class_func()`returns`Dummy` >>>out=Dummy.class_func() >>>outisDummy True #`Dummy`getspassedas`cls`automatically #evenwhen`class_func`iscalledfromaninstance >>>inst=Dummy() >>>inst.class_func() __main__.Dummy dict.fromkeysisanexampleofaclassmethodthattakesinaniterable,andreturnsadictionarywhosekeysaretheelementsofthatiterable,andwhosevaluesalldefaulttoNone. >>>dict.fromkeys("abcd",2.3) {'a':2.3,'b':2.3,'c':2.3,'d':2.3} Itissensiblethatthisisaclassmethodratherthananinstancemethod,asthemethodcreatesabrandnewdictionaryfromscratch.Itneedonlyhaveaccesstothedictobject(i.e. theclsargument)sothatitcanconstructthedictionary.Thefollowingiswhatanimplementationoffromkeyscouldlooklike,werewetodefinedictourselves: classdict: #assumeallotherdictionarymethodsaredefinedhere @classmethod deffromkeys(cls,iterable,value=None): """Createsadictionarywhosekeysaretheelementsof`iterable`.All keysmapto`value`. Parameters ---------- iterable:Iterable[Hashable] Aniterableofvaliddictionarykeys(i.e.anyobjectthatishashable). value:Optional[Any] Thevaluethatallofthekeyswillmapto.Defaultsto`None`. Returns ------- dict""" new_dict=cls()#equivalentto`dict()`:createsanewdictionaryinstance forkeyiniterable: new_dict[key]=value returnnew_dict StaticMethods Astaticmethodissimplyamethodwhoseargumentsmustallbepassedexplicitlybytheuser.Thatis,Pythondoesn’tpassanythingtoastaticmethodautomatically.Thebuilt-indecoratorstaticmethodisusedtodistinguishamethodasbeingstaticratherthananinstancemethod. classDummy: @staticmethod defstatic_func(): """Astaticmethoddefinedtoalwaysreturns thestring`'hi'`""" return'hi' #Astaticmethodcanbecalledfromaclassobject #oraninstanceobject;nothinggetspassedtoit #automatically. >>>Dummy.static_func() 'hi' >>>inst=Dummy() >>>inst.static_func() 'hi' ReadingComprehensionSolutions InvokingInstanceMethods:Solution RewriteDummysothatitsinstancemethodfuncacceptstwoarguments:theinstanceobjectthatPythonautomaticallypassesandtheargumentx,whichwewantfunctoreturnunchanged. Wewillrewitefunctoacceptanargumentcalled‘self’,whichwillaccepttheinstanceobjectthatispassed“underthehood”,and‘x’.Asyouwillseeinthereading,thenameargument‘self’issimplyusedbyconvention. classDummy: deffunc(self,x): returnx CreateaninstanceofDummyandcallfuncfromthisinstanceandpassitthestring"hi". >>>inst=Dummy() >>>inst.func("hi")#`inst`ispassedtotheargument`self` 'hi' WhatwillhappenifyoutrytocallDummy.func("hi")?Why? Thiswillraiseanerror,whichcomplainsthatfuncexpectstwoarguments,andthatwehaveonlypasseditone.Indeed,wewillhaveonlypassedittheobject“hi”andnothingelse.Dummyisaclassobject,notaninstanceobject.ThusPythondoesnotdoanythingspecial“underthehood”whenwecallDummy.func.Wemustpasssomethingtotheselfargument.Becausethisparticularmethoddoesn’tdoanythingwithself,wecanjustpassitNone,oranyotherobject,really. #Dummy.func("hi")wouldraiseanerror >>>Dummy.func(None,"hi") 'hi'



請為這篇文章評分?