Instruilo por la programlingvo Pitono

Bonvolu sendi korektojn, proponojn, kaj sugestojn al vilcxjo ĉe esperanto-me.org

Klasoj

Objektoj

Enkonduko al Klasoj

Klasaj objektoj
Instancaj objektoj
Metodaj objektoj
Datumaj Atribuoj
Nomado de Instancaj Objektoj
Klasa Ekzemplo


Objektoj

Avertu: la vorto 'objekto' en Pitono ne nepre signifas klasan instancon. Je Pitono, preskaŭ ĉiuj estas objektoj (ekz. ĉiuj datumaj tipoj, moduloj, kaj funkcioj). ĉi tiu provizas semantikojn por importado kaj renomado.

Ne ĉiuj tipoj en Pitonon estas klasoj: vi ne povas uzi primativajn tipojn kiel bazajn klasojn por etendi ilin. Dosieroj estas tipoj, sed ne estas klasoj. Tamen, ĉiuj Pitonaj tipoj kunhavas komunajn semantikojn kiu estas 'objekta'.

Fakte, klasoj mem estas objektoj, en la pli larĝa senco de la vorto.

Enkonduko al Klasoj

La plej simpla formo de klasa difino estas:

class KlasNomo:
     <instrukcio-1>
     .
     .
     <instrukcio-N>

Oni devas plenumi klasajn difinojn, same kiel funkciajn difinojn (def instrukcioj) por aktivigi ilin. (Vi povas plenumi klasan difinon nur kondiĉe aŭ en funkcio, sed kutime klasoj okazas je la komenco de la modulo).

Praktike, la instrukcioj en klasa difino kutime estos funkciajn difinojn, sed aliaj instrukcioj estas permesitaj, kaj malofte utilaj -- plu poste. La funkciaj difinoj en klaso kutime havas specialan formon de argumenta listo -- refoje, plu poste.

Kiam oni komencas plenumi klasan difinon, nova nomospaco estas kreita, kaj uzita kiel loka amplekso -- do, ĉiu asignoj al lokaj variabloj estas en ĉi tiu klasa nomospaco. Specife, la funkciaj difino kaj la funkcia nomo estas kunligitaj en la klasa nomospaco. Vidu leciono 'Nomospacoj kaj Valorizado' por pli informo pri nomospacoj kaj skopoj.

Kiam vi sukcese plenumas klasan difinon, klasa objekto estas kreita. Ĉi tiu estas volvaĵo ĉirkaŭ la enhavoj de la nomospaco de la klasa difino. La originala nomospaco (aktiva ĵus antaŭ la komenco de la klasa plenumo) estas remetita kaj la klasa objekto kaj la klasa nomo estas kunligitaj en ĉi tiu nomospaco.

Klasaj objektoj

Klasaj objektoj subtenas du tipojn da agadoj: atribuajn referencojn kaj generadon.

Atribuaj referencoj uzas la norman Pitonan sintakson: obj.nomo. Validaj atribuaj nomoj estas ĉiuj nomoj kiu estis en la klasa nomospaco kiam la klasa objekto estis kreita. Do, se la klasa difino aspektis jene:

   class MiaKlaso:
"Simpla ekzemplo klasa"
  i = 12345
  def f(q):
    sal = 'saluton mondo'
    return sal

tiam MiaKlaso.i and MiaKlaso.f estas validaj atribuaj referencoj, redonante entjeron kaj funkcian objekton, respektive. Vi povas ankaŭ asigni al klasaj atribuoj, do vi povas ŝanĝi la valoron de MiaKlaso.i per asigno. Aliaflanke, la variablo 'sal' ne estas atingebla.

Vi kreas klasan instancon per uzo de funkcia signaro. Ekz. (supozu la klason supre)

   v = MiaKlaso()

kreas novan instancon de la klaso kaj asignas ĉi tiun instancan objekton al la loka variablo v.

Instancaj objektoj

Kio vi povas fari per instancaj objektoj? La solaj agadoj kiun instancaj objektoj komprenas estas atribuoj referencoj. Estas du tipoj.

La unua estas datumaj atribuoj. (en aliaj programlingvoj, ĉi tiuj estas 'instancaj variabloj' aŭ 'datumaj membroj') . Datumaj atribuoj, same kiel lokaj variabloj, estas kreitaj kiam vi asignas al ilin. Ekz., (supozu la supran ekzemplon) la sekvaj instrukcioj videbligos la valoron 16 :

v.kvanto = 1
# kreu datuman atribuon
while v.kvanto < 10:
     v.kvanto = v.kvanto * 2
     print v.kvanto  
#videbligu rezulto
     del v.kvanto    
#senvalorigu ĝin

La dua estas metodoj. Metodo estas funkcion kiu apartenas al objekto. (ne nepre al klasaj instancoj - ekz., listoj havas metodojn). Tamen, en la cetero de ĉi tiu sekcio mi uzas la vorton 'metodo' aŭ 'metoda objekto' nur signifi metodon de klase instancaj objektoj, krom se mi eksplicite kontraŭdiras.

Validaj metodaj nomoj de instanca objekto dependas de ĝia klaso. Laŭ difino, ĉiuj atribuoj de klaso kiu estas funkciaj objektoj difinas respondajn metodojn de la instancoj. Do, en nia ekzemplo, v.f estas valida metoda referenco, ĉar MiaKlaso.f estas funkcio. Aliaflanke, v.i ne estas valida metoda referenco, ĉar MiaKlaso.i ne estas funkcio.

Sed, v.f ne estas la sama kiel MiaKlaso..f -- v.f estas metoda objekto; MiaKlaso.f estas funkcia objekto.

Metodaj objektoj

Kutime, vi vokas metodon tuje, ekz.,:

v.f()

En nia ekzemplo, ĉi tiu redonos la ĉenon 'saluton mondo'. Tamen, vi ne necese devas voki metodon tuje: v.f estas metoda objekto, kaj vi povas stapli ĝin kaj voki ĝin poste: ekz.,

vf = v.f
while 1:
   print vf()

ĉi tiu daŭrigos videbligi 'saluton mondo' denove kaj denove.

Rimarku, ke mi vokis la metodon v.f sen argumento, sed la funkcia difino postulas argumenton. La specialaĵo de metodoj estas, ke la objekto mem estas sendita kiel al unua argumento de la funkcio. Se vi sendas argumentojn al la metodo, la objekto estas aldonita kiel la unua argumento. En nia ekzemplo, la voko v.f() estas precize egala al MiaKlaso.f(v). Ĝenerale, instanco.metodo(arg1, arg2, k.t.p.) egalas Klaso.funkcio(instanco, arg1, arg2, k.t.p.)

Angle, oni kutime nomas la unua argumento 'self'. Ĉi tiu estas nur kutimo; la vorto 'self' ne havas signifon al Pitono (sed aliaj programoj eble anticipas la uzon de ĉi tiu nomo). En ĉi tiu instruilo, mi anstataŭe uzos la esperantan vorton 'mem'.

Metodoj povas voki aliajn metodojn. Ekz.:

class Sako:
  def malplenigu(mem):      mem.datumoj = []   def aldonu(mem, q):      mem.datumoj.append(q)   def aldonu_dufoje(mem, q):      mem.aldonu(q) 
#vokas alian metodon 'aldonu'
     mem.aldonu(q)

La kreado de instanco fakte kreas malplenan objekton. Ofte, vi volas, ke datumaj objektoj estas kreitaj en specifaj statoj. Por fari tion, klaso povas difini specialan metodon nomiĝas __init__.

Se klaso difinas metodon __init__ , la kreado de nova instanco aŭtomate plenumas la metodon __init__ por tiu instanco.

En la Sako ekzemplo (supre), ni povas aldoni:

def __init__(mem):
   mem.malplenigu()

Sekve, kiam ni kreas novan instancon

s = Sako()

la funkcio malplenigu kreas malplenan liston datumoj.

Kompreneble, la metodo __init__() povas havi argumentojn. Tiuokaze, argumentoj donitaj dum la instanca kreado estas senditaj al la metodo __init__. Ekz.:

>>>class Komplekso: ...   def __init__(mem, reelparto, imagparto): ...      mem.r = reelparto ...      mem.i = imagparto ...
>>> x = Komplekso(3.0,-4.5) >>> x.r, x.i
(3.0, -4.5)

Datumaj Atribuoj

Datumaj atribuoj estas haveblaj al metodoj kaj ordinaraj uzantoj. Pitono ne havas kapablecon por tute kaŝi datumojn. Klasaj datumaj atribuoj estas netuŝeblaj nur per konsento.

Uzantoj devus zorge uzi datumojn atribuojn. Uzantoj povas korupti metodojn per disrompo de iliaj datumaj atribuoj. Rimarku, ke uzanto povas aldoni iliajn proprajn datumajn atribuoj al instanca objekto sen malfavora rezulto, se nomaj konfliktoj estas evitaj. Bona noma sistemo sparos multajn problemojn ĉi tiajn (vidu 'Nomado de Instancaj Objektoj' sube).

Ne ekzistas mallongigojn en metodoj por referenci datumajn atribuojn aŭ aliajn metodojn. Ĉi tiu manko pligrandigas la klarecon de metodoj. Ne estas ebleco de konfuzo inter lokaj variabloj kaj instancaj variabloj.

Bona regulo: Ne rekte tuŝu datumajn atribuojn. Anstataŭe, uzu metodon resendi aŭ ŝanĝi valoron.

Nomado de Instancaj Objektoj

Datuma atribuo subpremas samnoman metodan atribuon. Por eviti akcidentajn nomajn konfliktojn, uzu ian noman ŝablonon kiu diferencigas la nomojn. Ekzemploj - majuskligu metodajn nomojn, aŭ prefiksu nomojn de datumaj atribuoj kun malgranda unika ĉeno (eble unu substreko), aŭ uzu verbojn por metodoj kaj substantivojn por datumaj atribuoj.

Klasa Ekzemplo

Starigi generalan stakan kapablecon per klaso (el "Programming Python", verkita de Mark Lutz):

class Stako:    def __init__(mem): #starigu stakon(liston)por ĉiu instanco       mem.stako = []    def puŝu(mem, objekto):    #aldonu al la fino de la stako(listo)       mem.stako.append(objekto)    def elprenu(mem):       supro = mem.stako[-1] #supro= la lasta       del mem.stako[-1] #forigu la lasta       return supro
   def malplena(mem):       return not mem.stako

La klaso povas esti en importota modulo nomita "StakoKlaso":

>>>from StakoKlaso import Stako >>>stako_1 = Stako()  #kreu unuan stakan instancon >>>stako_1.puŝu('ĉeno') #aldonu stakan eron >>>stako_1.puŝu(123)    #aldonu denove >>>stako_1.stako ['ĉeno', 123] >>>stako_2 = Stako()# dua instanco >>>stako_2.puŝu(stako_1.elprenu()) #movu >>>stako_1.stako, stako_2.stako (['ĉeno'], [123]) >>>if not stako_1.malplena(): ...   a = stako_1.elprenu() ... >>>a 'ĉeno'
Supren