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 defino estas:

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

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

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

Kiam oni komencas plenumi klasan definon, nova nomospaco estas kreita, kaj uzita kiel loka amplekso -- do, ĉiu asignoj al lokaj variabloj estas en ĉi tiu klasa nomospaco. Specife, la funkciaj defino 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 definon, klasa objekto estas kreita. Ĉi tiu estas volvaĵo ĉirkaŭ la enhavoj de la nomospaco de la klasa defino. 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 defino 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ŭ defino, ĉiuj atribuoj de klaso kiu estas funkciaj objektoj definas 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 defino 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 defini specialan metodon nomiĝas __init__.

Se klaso definas 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