9. Classes — Python 3.10.7 documentation

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

Python classes provide all the standard features of Object Oriented Programming: the class inheritance mechanism allows multiple base classes, a derived class ... Navigation index modules| next| previous| Python» 3.10.7Documentation» ThePythonTutorial» 9.Classes | 9.Classes¶ Classesprovideameansofbundlingdataandfunctionalitytogether.Creating anewclasscreatesanewtypeofobject,allowingnewinstancesofthat typetobemade.Eachclassinstancecanhaveattributesattachedtoitfor maintainingitsstate.Classinstancescanalsohavemethods(definedbyits class)formodifyingitsstate. Comparedwithotherprogramminglanguages,Python’sclassmechanismaddsclasses withaminimumofnewsyntaxandsemantics.Itisamixtureoftheclass mechanismsfoundinC++andModula-3.Pythonclassesprovideallthestandard featuresofObjectOrientedProgramming:theclassinheritancemechanismallows multiplebaseclasses,aderivedclasscanoverrideanymethodsofitsbase classorclasses,andamethodcancallthemethodofabaseclasswiththesame name.Objectscancontainarbitraryamountsandkindsofdata.Asistruefor modules,classespartakeofthedynamicnatureofPython:theyarecreatedat runtime,andcanbemodifiedfurtheraftercreation. InC++terminology,normallyclassmembers(includingthedatamembers)are public(exceptseebelowPrivateVariables),andallmemberfunctionsare virtual.AsinModula-3,therearenoshorthandsforreferencingtheobject’s membersfromitsmethods:themethodfunctionisdeclaredwithanexplicitfirst argumentrepresentingtheobject,whichisprovidedimplicitlybythecall.As inSmalltalk,classesthemselvesareobjects.Thisprovidessemanticsfor importingandrenaming.UnlikeC++andModula-3,built-intypescanbeusedas baseclassesforextensionbytheuser.Also,likeinC++,mostbuilt-in operatorswithspecialsyntax(arithmeticoperators,subscriptingetc.)canbe redefinedforclassinstances. (Lackinguniversallyacceptedterminologytotalkaboutclasses,Iwillmake occasionaluseofSmalltalkandC++terms.IwoulduseModula-3terms,since itsobject-orientedsemanticsareclosertothoseofPythonthanC++,butI expectthatfewreadershaveheardofit.) 9.1.AWordAboutNamesandObjects¶ Objectshaveindividuality,andmultiplenames(inmultiplescopes)canbebound tothesameobject.Thisisknownasaliasinginotherlanguages.Thisis usuallynotappreciatedonafirstglanceatPython,andcanbesafelyignored whendealingwithimmutablebasictypes(numbers,strings,tuples).However, aliasinghasapossiblysurprisingeffectonthesemanticsofPythoncode involvingmutableobjectssuchaslists,dictionaries,andmostothertypes. Thisisusuallyusedtothebenefitoftheprogram,sincealiasesbehavelike pointersinsomerespects.Forexample,passinganobjectischeapsinceonlya pointerispassedbytheimplementation;andifafunctionmodifiesanobject passedasanargument,thecallerwillseethechange—thiseliminatesthe needfortwodifferentargumentpassingmechanismsasinPascal. 9.2.PythonScopesandNamespaces¶ Beforeintroducingclasses,IfirsthavetotellyousomethingaboutPython’s scoperules.Classdefinitionsplaysomeneattrickswithnamespaces,andyou needtoknowhowscopesandnamespacesworktofullyunderstandwhat’sgoingon. Incidentally,knowledgeaboutthissubjectisusefulforanyadvancedPython programmer. Let’sbeginwithsomedefinitions. Anamespaceisamappingfromnamestoobjects.Mostnamespacesarecurrently implementedasPythondictionaries,butthat’snormallynotnoticeableinany way(exceptforperformance),anditmaychangeinthefuture.Examplesof namespacesare:thesetofbuilt-innames(containingfunctionssuchasabs(),and built-inexceptionnames);theglobalnamesinamodule;andthelocalnamesin afunctioninvocation.Inasensethesetofattributesofanobjectalsoform anamespace.Theimportantthingtoknowaboutnamespacesisthatthereis absolutelynorelationbetweennamesindifferentnamespaces;forinstance,two differentmodulesmaybothdefineafunctionmaximizewithoutconfusion— usersofthemodulesmustprefixitwiththemodulename. Bytheway,Iusethewordattributeforanynamefollowingadot—for example,intheexpressionz.real,realisanattributeoftheobject z.Strictlyspeaking,referencestonamesinmodulesareattribute references:intheexpressionmodname.funcname,modnameisamodule objectandfuncnameisanattributeofit.Inthiscasetherehappenstobe astraightforwardmappingbetweenthemodule’sattributesandtheglobalnames definedinthemodule:theysharethesamenamespace!1 Attributesmayberead-onlyorwritable.Inthelattercase,assignmentto attributesispossible.Moduleattributesarewritable:youcanwrite modname.the_answer=42.Writableattributesmayalsobedeletedwiththe delstatement.Forexample,delmodname.the_answerwillremove theattributethe_answerfromtheobjectnamedbymodname. Namespacesarecreatedatdifferentmomentsandhavedifferentlifetimes.The namespacecontainingthebuilt-innamesiscreatedwhenthePythoninterpreter startsup,andisneverdeleted.Theglobalnamespaceforamoduleiscreated whenthemoduledefinitionisreadin;normally,modulenamespacesalsolast untiltheinterpreterquits.Thestatementsexecutedbythetop-level invocationoftheinterpreter,eitherreadfromascriptfileorinteractively, areconsideredpartofamodulecalled__main__,sotheyhavetheirown globalnamespace.(Thebuilt-innamesactuallyalsoliveinamodule;thisis calledbuiltins.) Thelocalnamespaceforafunctioniscreatedwhenthefunctioniscalled,and deletedwhenthefunctionreturnsorraisesanexceptionthatisnothandled withinthefunction.(Actually,forgettingwouldbeabetterwaytodescribe whatactuallyhappens.)Ofcourse,recursiveinvocationseachhavetheirown localnamespace. AscopeisatextualregionofaPythonprogramwhereanamespaceisdirectly accessible.“Directlyaccessible”heremeansthatanunqualifiedreferencetoa nameattemptstofindthenameinthenamespace. Althoughscopesaredeterminedstatically,theyareuseddynamically.Atany timeduringexecution,thereare3or4nestedscopeswhosenamespacesare directlyaccessible: theinnermostscope,whichissearchedfirst,containsthelocalnames thescopesofanyenclosingfunctions,whicharesearchedstartingwiththe nearestenclosingscope,containsnon-local,butalsonon-globalnames thenext-to-lastscopecontainsthecurrentmodule’sglobalnames theoutermostscope(searchedlast)isthenamespacecontainingbuilt-innames Ifanameisdeclaredglobal,thenallreferencesandassignmentsgodirectlyto themiddlescopecontainingthemodule’sglobalnames.Torebindvariables foundoutsideoftheinnermostscope,thenonlocalstatementcanbe used;ifnotdeclarednonlocal,thosevariablesareread-only(anattemptto writetosuchavariablewillsimplycreateanewlocalvariableinthe innermostscope,leavingtheidenticallynamedoutervariableunchanged). Usually,thelocalscopereferencesthelocalnamesofthe(textually)current function.Outsidefunctions,thelocalscopereferencesthesamenamespaceas theglobalscope:themodule’snamespace.Classdefinitionsplaceyetanother namespaceinthelocalscope. Itisimportanttorealizethatscopesaredeterminedtextually:theglobal scopeofafunctiondefinedinamoduleisthatmodule’snamespace,nomatter fromwhereorbywhataliasthefunctioniscalled.Ontheotherhand,the actualsearchfornamesisdonedynamically,atruntime—however,the languagedefinitionisevolvingtowardsstaticnameresolution,at“compile” time,sodon’trelyondynamicnameresolution!(Infact,localvariablesare alreadydeterminedstatically.) AspecialquirkofPythonisthat–ifnoglobalornonlocal statementisineffect–assignmentstonamesalwaysgointotheinnermostscope. Assignmentsdonotcopydata—theyjustbindnamestoobjects.Thesameistrue fordeletions:thestatementdelxremovesthebindingofxfromthe namespacereferencedbythelocalscope.Infact,alloperationsthatintroduce newnamesusethelocalscope:inparticular,importstatementsand functiondefinitionsbindthemoduleorfunctionnameinthelocalscope. Theglobalstatementcanbeusedtoindicatethatparticular variablesliveintheglobalscopeandshouldbereboundthere;the nonlocalstatementindicatesthatparticularvariableslivein anenclosingscopeandshouldbereboundthere. 9.2.1.ScopesandNamespacesExample¶ Thisisanexampledemonstratinghowtoreferencethedifferentscopesand namespaces,andhowglobalandnonlocalaffectvariable binding: defscope_test(): defdo_local(): spam="localspam" defdo_nonlocal(): nonlocalspam spam="nonlocalspam" defdo_global(): globalspam spam="globalspam" spam="testspam" do_local() print("Afterlocalassignment:",spam) do_nonlocal() print("Afternonlocalassignment:",spam) do_global() print("Afterglobalassignment:",spam) scope_test() print("Inglobalscope:",spam) Theoutputoftheexamplecodeis: Afterlocalassignment:testspam Afternonlocalassignment:nonlocalspam Afterglobalassignment:nonlocalspam Inglobalscope:globalspam Notehowthelocalassignment(whichisdefault)didn’tchangescope_test's bindingofspam.Thenonlocalassignmentchangedscope_test's bindingofspam,andtheglobalassignmentchangedthemodule-level binding. Youcanalsoseethattherewasnopreviousbindingforspambeforethe globalassignment. 9.3.AFirstLookatClasses¶ Classesintroducealittlebitofnewsyntax,threenewobjecttypes,andsome newsemantics. 9.3.1.ClassDefinitionSyntax¶ Thesimplestformofclassdefinitionlookslikethis: classClassName: . . . Classdefinitions,likefunctiondefinitions(defstatements)mustbe executedbeforetheyhaveanyeffect.(Youcouldconceivablyplaceaclass definitioninabranchofanifstatement,orinsideafunction.) Inpractice,thestatementsinsideaclassdefinitionwillusuallybefunction definitions,butotherstatementsareallowed,andsometimesuseful—we’ll comebacktothislater.Thefunctiondefinitionsinsideaclassnormallyhave apeculiarformofargumentlist,dictatedbythecallingconventionsfor methods—again,thisisexplainedlater. Whenaclassdefinitionisentered,anewnamespaceiscreated,andusedasthe localscope—thus,allassignmentstolocalvariablesgointothisnew namespace.Inparticular,functiondefinitionsbindthenameofthenew functionhere. Whenaclassdefinitionisleftnormally(viatheend),aclassobjectis created.Thisisbasicallyawrapperaroundthecontentsofthenamespace createdbytheclassdefinition;we’lllearnmoreaboutclassobjectsinthe nextsection.Theoriginallocalscope(theoneineffectjustbeforetheclass definitionwasentered)isreinstated,andtheclassobjectisboundheretothe classnamegivenintheclassdefinitionheader(ClassNameinthe example). 9.3.2.ClassObjects¶ Classobjectssupporttwokindsofoperations:attributereferencesand instantiation. Attributereferencesusethestandardsyntaxusedforallattributereferences inPython:obj.name.Validattributenamesareallthenamesthatwerein theclass’snamespacewhentheclassobjectwascreated.So,iftheclass definitionlookedlikethis: classMyClass: """Asimpleexampleclass""" i=12345 deff(self): return'helloworld' thenMyClass.iandMyClass.farevalidattributereferences,returning anintegerandafunctionobject,respectively.Classattributescanalsobe assignedto,soyoucanchangethevalueofMyClass.ibyassignment. __doc__isalsoavalidattribute,returningthedocstringbelongingto theclass:"Asimpleexampleclass". Classinstantiationusesfunctionnotation.Justpretendthattheclass objectisaparameterlessfunctionthatreturnsanewinstanceoftheclass. Forexample(assumingtheaboveclass): x=MyClass() createsanewinstanceoftheclassandassignsthisobjecttothelocal variablex. Theinstantiationoperation(“calling”aclassobject)createsanemptyobject. Manyclassesliketocreateobjectswithinstancescustomizedtoaspecific initialstate.Thereforeaclassmaydefineaspecialmethodnamed __init__(),likethis: def__init__(self): self.data=[] Whenaclassdefinesan__init__()method,classinstantiation automaticallyinvokes__init__()forthenewlycreatedclassinstance.So inthisexample,anew,initializedinstancecanbeobtainedby: x=MyClass() Ofcourse,the__init__()methodmayhaveargumentsforgreater flexibility.Inthatcase,argumentsgiventotheclassinstantiationoperator arepassedonto__init__().Forexample, >>>classComplex: ...def__init__(self,realpart,imagpart): ...self.r=realpart ...self.i=imagpart ... >>>x=Complex(3.0,-4.5) >>>x.r,x.i (3.0,-4.5) 9.3.3.InstanceObjects¶ Nowwhatcanwedowithinstanceobjects?Theonlyoperationsunderstoodby instanceobjectsareattributereferences.Therearetwokindsofvalid attributenames:dataattributesandmethods. dataattributescorrespondto“instancevariables”inSmalltalk,andto“data members”inC++.Dataattributesneednotbedeclared;likelocalvariables, theyspringintoexistencewhentheyarefirstassignedto.Forexample,if xistheinstanceofMyClasscreatedabove,thefollowingpieceof codewillprintthevalue16,withoutleavingatrace: x.counter=1 whilex.counter<10: x.counter=x.counter*2 print(x.counter) delx.counter Theotherkindofinstanceattributereferenceisamethod.Amethodisa functionthat“belongsto”anobject.(InPython,thetermmethodisnotunique toclassinstances:otherobjecttypescanhavemethodsaswell.Forexample, listobjectshavemethodscalledappend,insert,remove,sort,andsoon. However,inthefollowingdiscussion,we’llusethetermmethodexclusivelyto meanmethodsofclassinstanceobjects,unlessexplicitlystatedotherwise.) Validmethodnamesofaninstanceobjectdependonitsclass.Bydefinition, allattributesofaclassthatarefunctionobjectsdefinecorresponding methodsofitsinstances.Soinourexample,x.fisavalidmethod reference,sinceMyClass.fisafunction,butx.iisnot,since MyClass.iisnot.Butx.fisnotthesamethingasMyClass.f—it isamethodobject,notafunctionobject. 9.3.4.MethodObjects¶ Usually,amethodiscalledrightafteritisbound: x.f() IntheMyClassexample,thiswillreturnthestring'helloworld'. However,itisnotnecessarytocallamethodrightaway:x.fisamethod object,andcanbestoredawayandcalledatalatertime.Forexample: xf=x.f whileTrue: print(xf()) willcontinuetoprinthelloworlduntiltheendoftime. Whatexactlyhappenswhenamethodiscalled?Youmayhavenoticedthat x.f()wascalledwithoutanargumentabove,eventhoughthefunction definitionforf()specifiedanargument.Whathappenedtotheargument? SurelyPythonraisesanexceptionwhenafunctionthatrequiresanargumentis calledwithoutany—eveniftheargumentisn’tactuallyused… Actually,youmayhaveguessedtheanswer:thespecialthingaboutmethodsis thattheinstanceobjectispassedasthefirstargumentofthefunction.Inour example,thecallx.f()isexactlyequivalenttoMyClass.f(x).In general,callingamethodwithalistofnargumentsisequivalenttocalling thecorrespondingfunctionwithanargumentlistthatiscreatedbyinserting themethod’sinstanceobjectbeforethefirstargument. Ifyoustilldon’tunderstandhowmethodswork,alookattheimplementationcan perhapsclarifymatters.Whenanon-dataattributeofaninstanceis referenced,theinstance’sclassissearched.Ifthenamedenotesavalidclass attributethatisafunctionobject,amethodobjectiscreatedbypacking (pointersto)theinstanceobjectandthefunctionobjectjustfoundtogetherin anabstractobject:thisisthemethodobject.Whenthemethodobjectiscalled withanargumentlist,anewargumentlistisconstructedfromtheinstance objectandtheargumentlist,andthefunctionobjectiscalledwiththisnew argumentlist. 9.3.5.ClassandInstanceVariables¶ Generallyspeaking,instancevariablesarefordatauniquetoeachinstance andclassvariablesareforattributesandmethodssharedbyallinstances oftheclass: classDog: kind='canine'#classvariablesharedbyallinstances def__init__(self,name): self.name=name#instancevariableuniquetoeachinstance >>>d=Dog('Fido') >>>e=Dog('Buddy') >>>d.kind#sharedbyalldogs 'canine' >>>e.kind#sharedbyalldogs 'canine' >>>d.name#uniquetod 'Fido' >>>e.name#uniquetoe 'Buddy' AsdiscussedinAWordAboutNamesandObjects,shareddatacanhavepossiblysurprising effectswithinvolvingmutableobjectssuchaslistsanddictionaries. Forexample,thetrickslistinthefollowingcodeshouldnotbeusedasa classvariablebecausejustasinglelistwouldbesharedbyallDog instances: classDog: tricks=[]#mistakenuseofaclassvariable def__init__(self,name): self.name=name defadd_trick(self,trick): self.tricks.append(trick) >>>d=Dog('Fido') >>>e=Dog('Buddy') >>>d.add_trick('rollover') >>>e.add_trick('playdead') >>>d.tricks#unexpectedlysharedbyalldogs ['rollover','playdead'] Correctdesignoftheclassshoulduseaninstancevariableinstead: classDog: def__init__(self,name): self.name=name self.tricks=[]#createsanewemptylistforeachdog defadd_trick(self,trick): self.tricks.append(trick) >>>d=Dog('Fido') >>>e=Dog('Buddy') >>>d.add_trick('rollover') >>>e.add_trick('playdead') >>>d.tricks ['rollover'] >>>e.tricks ['playdead'] 9.4.RandomRemarks¶ Ifthesameattributenameoccursinbothaninstanceandinaclass, thenattributelookupprioritizestheinstance: >>>classWarehouse: ...purpose='storage' ...region='west' ... >>>w1=Warehouse() >>>print(w1.purpose,w1.region) storagewest >>>w2=Warehouse() >>>w2.region='east' >>>print(w2.purpose,w2.region) storageeast Dataattributesmaybereferencedbymethodsaswellasbyordinaryusers (“clients”)ofanobject.Inotherwords,classesarenotusabletoimplement pureabstractdatatypes.Infact,nothinginPythonmakesitpossibleto enforcedatahiding—itisallbaseduponconvention.(Ontheotherhand, thePythonimplementation,writteninC,cancompletelyhideimplementation detailsandcontrolaccesstoanobjectifnecessary;thiscanbeusedby extensionstoPythonwritteninC.) Clientsshouldusedataattributeswithcare—clientsmaymessupinvariants maintainedbythemethodsbystampingontheirdataattributes.Notethat clientsmayadddataattributesoftheirowntoaninstanceobjectwithout affectingthevalidityofthemethods,aslongasnameconflictsareavoided— again,anamingconventioncansavealotofheadacheshere. Thereisnoshorthandforreferencingdataattributes(orothermethods!)from withinmethods.Ifindthatthisactuallyincreasesthereadabilityofmethods: thereisnochanceofconfusinglocalvariablesandinstancevariableswhen glancingthroughamethod. Often,thefirstargumentofamethodiscalledself.Thisisnothingmore thanaconvention:thenameselfhasabsolutelynospecialmeaningto Python.Note,however,thatbynotfollowingtheconventionyourcodemaybe lessreadabletootherPythonprogrammers,anditisalsoconceivablethata classbrowserprogrammightbewrittenthatreliesuponsuchaconvention. Anyfunctionobjectthatisaclassattributedefinesamethodforinstancesof thatclass.Itisnotnecessarythatthefunctiondefinitionistextually enclosedintheclassdefinition:assigningafunctionobjecttoalocal variableintheclassisalsook.Forexample: #Functiondefinedoutsidetheclass deff1(self,x,y): returnmin(x,x+y) classC: f=f1 defg(self): return'helloworld' h=g Nowf,gandhareallattributesofclassCthatreferto functionobjects,andconsequentlytheyareallmethodsofinstancesof C—hbeingexactlyequivalenttog.Notethatthispractice usuallyonlyservestoconfusethereaderofaprogram. Methodsmaycallothermethodsbyusingmethodattributesoftheself argument: classBag: def__init__(self): self.data=[] defadd(self,x): self.data.append(x) defaddtwice(self,x): self.add(x) self.add(x) Methodsmayreferenceglobalnamesinthesamewayasordinaryfunctions.The globalscopeassociatedwithamethodisthemodulecontainingits definition.(Aclassisneverusedasaglobalscope.)Whileone rarelyencountersagoodreasonforusingglobaldatainamethod,thereare manylegitimateusesoftheglobalscope:foronething,functionsandmodules importedintotheglobalscopecanbeusedbymethods,aswellasfunctionsand classesdefinedinit.Usually,theclasscontainingthemethodisitself definedinthisglobalscope,andinthenextsectionwe’llfindsomegood reasonswhyamethodwouldwanttoreferenceitsownclass. Eachvalueisanobject,andthereforehasaclass(alsocalleditstype). Itisstoredasobject.__class__. 9.5.Inheritance¶ Ofcourse,alanguagefeaturewouldnotbeworthyofthename“class”without supportinginheritance.Thesyntaxforaderivedclassdefinitionlookslike this: classDerivedClassName(BaseClassName): . . . ThenameBaseClassNamemustbedefinedinascopecontainingthe derivedclassdefinition.Inplaceofabaseclassname,otherarbitrary expressionsarealsoallowed.Thiscanbeuseful,forexample,whenthebase classisdefinedinanothermodule: classDerivedClassName(modname.BaseClassName): Executionofaderivedclassdefinitionproceedsthesameasforabaseclass. Whentheclassobjectisconstructed,thebaseclassisremembered.Thisis usedforresolvingattributereferences:ifarequestedattributeisnotfound intheclass,thesearchproceedstolookinthebaseclass.Thisruleis appliedrecursivelyifthebaseclassitselfisderivedfromsomeotherclass. There’snothingspecialaboutinstantiationofderivedclasses: DerivedClassName()createsanewinstanceoftheclass.Methodreferences areresolvedasfollows:thecorrespondingclassattributeissearched, descendingdownthechainofbaseclassesifnecessary,andthemethodreference isvalidifthisyieldsafunctionobject. Derivedclassesmayoverridemethodsoftheirbaseclasses.Becausemethods havenospecialprivilegeswhencallingothermethodsofthesameobject,a methodofabaseclassthatcallsanothermethoddefinedinthesamebaseclass mayendupcallingamethodofaderivedclassthatoverridesit.(ForC++ programmers:allmethodsinPythonareeffectivelyvirtual.) Anoverridingmethodinaderivedclassmayinfactwanttoextendratherthan simplyreplacethebaseclassmethodofthesamename.Thereisasimplewayto callthebaseclassmethoddirectly:justcallBaseClassName.methodname(self, arguments).Thisisoccasionallyusefultoclientsaswell.(Notethatthis onlyworksifthebaseclassisaccessibleasBaseClassNameintheglobal scope.) Pythonhastwobuilt-infunctionsthatworkwithinheritance: Useisinstance()tocheckaninstance’stype:isinstance(obj,int) willbeTrueonlyifobj.__class__isintorsomeclass derivedfromint. Useissubclass()tocheckclassinheritance:issubclass(bool,int) isTruesinceboolisasubclassofint.However, issubclass(float,int)isFalsesincefloatisnota subclassofint. 9.5.1.MultipleInheritance¶ Pythonsupportsaformofmultipleinheritanceaswell.Aclassdefinitionwith multiplebaseclasseslookslikethis: classDerivedClassName(Base1,Base2,Base3): . . . Formostpurposes,inthesimplestcases,youcanthinkofthesearchfor attributesinheritedfromaparentclassasdepth-first,left-to-right,not searchingtwiceinthesameclasswherethereisanoverlapinthehierarchy. Thus,ifanattributeisnotfoundinDerivedClassName,itissearched forinBase1,then(recursively)inthebaseclassesofBase1, andifitwasnotfoundthere,itwassearchedforinBase2,andsoon. Infact,itisslightlymorecomplexthanthat;themethodresolutionorder changesdynamicallytosupportcooperativecallstosuper().This approachisknowninsomeothermultiple-inheritancelanguagesas call-next-methodandismorepowerfulthanthesupercallfoundin single-inheritancelanguages. Dynamicorderingisnecessarybecauseallcasesofmultipleinheritanceexhibit oneormorediamondrelationships(whereatleastoneoftheparentclasses canbeaccessedthroughmultiplepathsfromthebottommostclass).Forexample, allclassesinheritfromobject,soanycaseofmultipleinheritance providesmorethanonepathtoreachobject.Tokeepthebaseclasses frombeingaccessedmorethanonce,thedynamicalgorithmlinearizesthesearch orderinawaythatpreservestheleft-to-rightorderingspecifiedineach class,thatcallseachparentonlyonce,andthatismonotonic(meaningthata classcanbesubclassedwithoutaffectingtheprecedenceorderofitsparents). Takentogether,thesepropertiesmakeitpossibletodesignreliableand extensibleclasseswithmultipleinheritance.Formoredetail,see https://www.python.org/download/releases/2.3/mro/. 9.6.PrivateVariables¶ “Private”instancevariablesthatcannotbeaccessedexceptfrominsidean objectdon’texistinPython.However,thereisaconventionthatisfollowed bymostPythoncode:anameprefixedwithanunderscore(e.g._spam)should betreatedasanon-publicpartoftheAPI(whetheritisafunction,amethod oradatamember).Itshouldbeconsideredanimplementationdetailandsubject tochangewithoutnotice. Sincethereisavaliduse-caseforclass-privatemembers(namelytoavoidname clashesofnameswithnamesdefinedbysubclasses),thereislimitedsupportfor suchamechanism,callednamemangling.Anyidentifieroftheform __spam(atleasttwoleadingunderscores,atmostonetrailingunderscore) istextuallyreplacedwith_classname__spam,whereclassnameisthe currentclassnamewithleadingunderscore(s)stripped.Thismanglingisdone withoutregardtothesyntacticpositionoftheidentifier,aslongasit occurswithinthedefinitionofaclass. Namemanglingishelpfulforlettingsubclassesoverridemethodswithout breakingintraclassmethodcalls.Forexample: classMapping: def__init__(self,iterable): self.items_list=[] self.__update(iterable) defupdate(self,iterable): foriteminiterable: self.items_list.append(item) __update=update#privatecopyoforiginalupdate()method classMappingSubclass(Mapping): defupdate(self,keys,values): #providesnewsignatureforupdate() #butdoesnotbreak__init__() foriteminzip(keys,values): self.items_list.append(item) TheaboveexamplewouldworkevenifMappingSubclassweretointroducea __updateidentifiersinceitisreplacedwith_Mapping__updateinthe Mappingclassand_MappingSubclass__updateintheMappingSubclass classrespectively. Notethatthemanglingrulesaredesignedmostlytoavoidaccidents;itstillis possibletoaccessormodifyavariablethatisconsideredprivate.Thiscan evenbeusefulinspecialcircumstances,suchasinthedebugger. Noticethatcodepassedtoexec()oreval()doesnotconsiderthe classnameoftheinvokingclasstobethecurrentclass;thisissimilartothe effectoftheglobalstatement,theeffectofwhichislikewiserestricted tocodethatisbyte-compiledtogether.Thesamerestrictionappliesto getattr(),setattr()anddelattr(),aswellaswhenreferencing __dict__directly. 9.7.OddsandEnds¶ SometimesitisusefultohaveadatatypesimilartothePascal“record”orC “struct”,bundlingtogetherafewnameddataitems.Anemptyclassdefinition willdonicely: classEmployee: pass john=Employee()#Createanemptyemployeerecord #Fillthefieldsoftherecord john.name='JohnDoe' john.dept='computerlab' john.salary=1000 ApieceofPythoncodethatexpectsaparticularabstractdatatypecanoftenbe passedaclassthatemulatesthemethodsofthatdatatypeinstead.For instance,ifyouhaveafunctionthatformatssomedatafromafileobject,you candefineaclasswithmethodsread()andreadline()thatgetthe datafromastringbufferinstead,andpassitasanargument. Instancemethodobjectshaveattributes,too:m.__self__istheinstance objectwiththemethodm(),andm.__func__isthefunctionobject correspondingtothemethod. 9.8.Iterators¶ Bynowyouhaveprobablynoticedthatmostcontainerobjectscanbeloopedover usingaforstatement: forelementin[1,2,3]: print(element) forelementin(1,2,3): print(element) forkeyin{'one':1,'two':2}: print(key) forcharin"123": print(char) forlineinopen("myfile.txt"): print(line,end='') Thisstyleofaccessisclear,concise,andconvenient.Theuseofiterators pervadesandunifiesPython.Behindthescenes,theforstatement callsiter()onthecontainerobject.Thefunctionreturnsaniterator objectthatdefinesthemethod__next__()whichaccesses elementsinthecontaineroneatatime.Whentherearenomoreelements, __next__()raisesaStopIterationexceptionwhichtellsthe forlooptoterminate.Youcancallthe__next__()method usingthenext()built-infunction;thisexampleshowshowitallworks: >>>s='abc' >>>it=iter(s) >>>it >>>next(it) 'a' >>>next(it) 'b' >>>next(it) 'c' >>>next(it) Traceback(mostrecentcalllast): File"",line1,in next(it) StopIteration Havingseenthemechanicsbehindtheiteratorprotocol,itiseasytoadd iteratorbehaviortoyourclasses.Definean__iter__()methodwhich returnsanobjectwitha__next__()method.Iftheclass defines__next__(),then__iter__()canjustreturnself: classReverse: """Iteratorforloopingoverasequencebackwards.""" def__init__(self,data): self.data=data self.index=len(data) def__iter__(self): returnself def__next__(self): ifself.index==0: raiseStopIteration self.index=self.index-1 returnself.data[self.index] >>>rev=Reverse('spam') >>>iter(rev) <__main__.reverseobjectat0x00a1db50> >>>forcharinrev: ...print(char) ... m a p s 9.9.Generators¶ Generatorsareasimpleandpowerfultoolforcreatingiterators.They arewrittenlikeregularfunctionsbutusetheyieldstatement whenevertheywanttoreturndata.Eachtimenext()iscalledonit,the generatorresumeswhereitleftoff(itremembersallthedatavaluesandwhich statementwaslastexecuted).Anexampleshowsthatgeneratorscanbetrivially easytocreate: defreverse(data): forindexinrange(len(data)-1,-1,-1): yielddata[index] >>>forcharinreverse('golf'): ...print(char) ... f l o g Anythingthatcanbedonewithgeneratorscanalsobedonewithclass-based iteratorsasdescribedintheprevioussection.Whatmakesgeneratorsso compactisthatthe__iter__()and__next__()methods arecreatedautomatically. Anotherkeyfeatureisthatthelocalvariablesandexecutionstateare automaticallysavedbetweencalls.Thismadethefunctioneasiertowriteand muchmoreclearthananapproachusinginstancevariableslikeself.index andself.data. Inadditiontoautomaticmethodcreationandsavingprogramstate,when generatorsterminate,theyautomaticallyraiseStopIteration.In combination,thesefeaturesmakeiteasytocreateiteratorswithnomoreeffort thanwritingaregularfunction. 9.10.GeneratorExpressions¶ Somesimplegeneratorscanbecodedsuccinctlyasexpressionsusingasyntax similartolistcomprehensionsbutwithparenthesesinsteadofsquarebrackets. Theseexpressionsaredesignedforsituationswherethegeneratorisusedright awaybyanenclosingfunction.Generatorexpressionsaremorecompactbutless versatilethanfullgeneratordefinitionsandtendtobemorememoryfriendly thanequivalentlistcomprehensions. Examples: >>>sum(i*iforiinrange(10))#sumofsquares 285 >>>xvec=[10,20,30] >>>yvec=[7,5,3] >>>sum(x*yforx,yinzip(xvec,yvec))#dotproduct 260 >>>unique_words=set(wordforlineinpageforwordinline.split()) >>>valedictorian=max((student.gpa,student.name)forstudentingraduates) >>>data='golf' >>>list(data[i]foriinrange(len(data)-1,-1,-1)) ['f','l','o','g'] Footnotes 1 Exceptforonething.Moduleobjectshaveasecretread-onlyattributecalled __dict__whichreturnsthedictionaryusedtoimplementthemodule’s namespace;thename__dict__isanattributebutnotaglobalname. Obviously,usingthisviolatestheabstractionofnamespaceimplementation,and shouldberestrictedtothingslikepost-mortemdebuggers. TableofContents 9.Classes 9.1.AWordAboutNamesandObjects 9.2.PythonScopesandNamespaces 9.2.1.ScopesandNamespacesExample 9.3.AFirstLookatClasses 9.3.1.ClassDefinitionSyntax 9.3.2.ClassObjects 9.3.3.InstanceObjects 9.3.4.MethodObjects 9.3.5.ClassandInstanceVariables 9.4.RandomRemarks 9.5.Inheritance 9.5.1.MultipleInheritance 9.6.PrivateVariables 9.7.OddsandEnds 9.8.Iterators 9.9.Generators 9.10.GeneratorExpressions Previoustopic 8.ErrorsandExceptions Nexttopic 10.BriefTouroftheStandardLibrary ThisPage ReportaBug ShowSource Navigation index modules| next| previous| Python» 3.10.7Documentation» ThePythonTutorial» 9.Classes |



請為這篇文章評分?