Enhavolisto

Antaŭa temo

7. Regi fluon

Sekva temo

9. Listoj - kondiĉoj - komparoj

8. Funkcioj

Ni povas difini funkcion kiu skribas la Fibonaĉian serion ĝis difinita limo:

>>> def fib(n): #skribu Fibonaĉian serion ĝis n
...   """Skribu Fibonaĉian serion ĝis n"""
...   a, b = 0, 1
...   while b < n:
...      print b,
...      a, b = b, a+b
...
>>> # Nun voku la funkcion ni ĵus difinis
... fib(2000)
1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597

La vorto def enkondukas funkcian difinon. Sekve, devas esti funkcia nomo kaj interkrampa listo de formalaj parametroj (argumentoj). La kodogrupo kiu formas la korpon de la funkcio komencas je la sekvonta linio, kun pli de marĝeno. La unua linio(j)en la kodogrupo povas esti ĉena(j) datumo(j); tiu(j) estas dokumento por la funkcio.

Estas iloj, kiu uzas tiajn dokumentajn ĉenojn por aŭtomate krei presitan dokumentadon aŭ lasu la uzanto dialoge trarigardi la fontokodon; estas bona praktiko enhavigi tiajn dokumentajn ĉenojn en kodo kiun oni skribas, do provu fari tion kutime.

Funkcia plenumo (ne difino) enkondukas novan simboltabelon kiu enhavas la lokajn variablojn de la funkcio. Pli precize, ciu variabla valorizo en funkcio staplas la valoron en la lokan simboltabelon. Tamen variablaj referencoj unue kontrolas la lokan simboltabelon, poste la mallokan simboltabelon. Poste la tabelon de primitivaj nomoj. Do, oni ne povas valorizi mallokajn variablojn interne al funkcio (krom la variablo estas nomita en instrukcio global), tamen oni povas referenci ilin. (Kontrolu lecionon pri Nomospacoj kaj valorizado por plua klarigo kaj ekzemploj)

La argumentoj de funkcio estas enkondukitaj en la lokan simboltabelon de la vokata funkcio kiam ĝi estas vokata; do, la argumentoj estas pasigita per objekta referenco. Se ŝanĝebla objekto estas donita, la vokanto vidos iu ajn ŝanĝojn faritajn de vokato. Kiam funkcio vokas alian funkcion, nova simboltabelo estas kreita por ĉi tiu voko.

Funkcia difino enkondukas la funkcian nomon en la aktuala simboltabelo. Oni povas asigni funkcian nomon al alia variablo, kiun oni povas uzi por voki la originalan funkcion. Rezulto estas kaŝnomo.

>>> fib
<function object at 10042ed0>
>>> f = fib
>>> f(100)
1 1 2 3 5 8 13 21 34 55 89

En Pitono, proceduro estas nur tipo de funkcio kiu ne resendas valoro(j)n. Fakte, proceduroj resendas valoron None (primitiva vorto kiu signifas nenion).

>>> print fib(0)
None

Estas simpla afero skribi funkcion kiu resendas liston de la numeroj el la Fibonaĉia serio, anstataŭ videbligi ĝin:

>>> def fib2(n):
...    """Resendi Fibonaĉian serion ĝis n"""
...    rezulto = []
...    a, b = 0, 1
...    while b < n:
...       rezulto.append(b)
...       a, b = b, a+b
...    return rezulto
...
>>> f100 = fib2(100) # voku funkcion
>>> f100 # skribu rezulton
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]

Ĉi tiu ekzemplo montras novajn Pitonajn trajtojn:

  • La instrukcio return revenas kun valoro de funkcio. Oni uzas instrukcion return sen argumento por reveni kun valoro None (same, funkcio sen instrukcio return resendas valoron None).
  • La instrukcio rezulto.append(b) vokas metodon de la lista objekto rezulto. Metodo estas funkcion kiu ‘apartenas’ al objekto kaj estas nomita obj.metodonomo, kie obj estas objekto (eble esprimo) kaj metodonomo estas nomo de metodo kiun la tipo de la objekto difinas.
  • Malsamaj objektoj difinas malsamajn metodojn. Metodoj de malsamaj tipoj povas havi la samajn nomojn sen duba senco.
  • Oni povas difini onian propran objektajn tipojn kaj metodojn, per uzo de klasoj, kiel estas klarigita en leciono Klasoj.
  • La metodo append() en la ekzemplo estas difinita por listaj objektoj; ĝi aldonas novan elementon je la fino de la listo. Por ĉi tiu ekzemplo, ĝi egalas al esprimo rezulto = rezulto + [b], sed estas pli efika.

8.1. Implicitaj argumentaj valoroj

Oni povas provizi implicitan valoron por unu aŭ pluraj argumentoj. Ĉi tiu kreas funkcion kiun oni povas voki kun malpli da argumentoj ol tiuj, kiuj estas difinitaj, ekz.:

>>> def petu_ok(invito, reprovoj=4,plendo='Jes aŭ ne, mi petas!'):
>>> while True:
>>>     ok = raw_input(invito)
>>>     if ok in ('j', 'je', 'jes'): return True
>>>     if ok in ('n', 'ne'): return False
>>>     reprovoj = reprovoj - 1
>>>     if reprovoj < 0:
>>>         raise IOError, 'refuzema uzanto'
>>>     print plendo

Oni povas voki ĉi tiun funkcion jene:

>>> petu_ok('ĉu oni ja volas rezigni?')

aŭ jene:

>>> petu_ok('ĉu reskribi dosieron estas permesata?', 2)

La implicitaj valoroj estas kalkulitaj je la punkto en la programa fluo kie funkcia difino okazas, do ekz:

>>> i = 5
>>> def f(arg = i):
...     print arg
>>> i = 6
>>> f()

videbligos 5.

Grava

La implicita valoro estas elvalorigita nur unufoje. Tio havas signifon, kiam implicito estas ŝanĝebla objekto kiel listo, ktp. Ekzemple, la jena funkcio akumulas argumentojn donitajn, kiam vokata multfoje.

>>> def f(a, L=[]):
...     L.append(a)
...     return L
...
>>> print f(1)
[1]
>>> print f(2)
[1, 2]
>>> print f(3)
[1, 2, 3]

Se oni ne volas akumuli argumentojn, skribu anstataŭe:

>>> def f(a, L=None):
...     if L is None:
...         L = []
...     L.append(a)
...     return L

8.2. Ŝlosilvortaj argumentoj en funkcioj

Funkcioj ankaŭ povas esti vokata per la uzo de ŝlosilvortaj argumentoj en la formo ‘ŝlosilvorto = valoro’. Ekzemple la jena funkcio

>>> def papago(voltkvanto, stato='morta', agado='voom'):
...     print "-- ĉi tiu papago ne volas", agado,
...     print "se vi aplikas ", voltkvanto, "voltoj al ĝi."
...     print "-- "Estas", stato, "!"

povas esti vokata per iu ajn de la sekvaj manieroj:

papago(1000)
papago(agado = 'VOOOOOM', voltkvanto = 1000000)
papago('mil', stato = 'preta por entombiĝo')
papago('miliono', 'tute senviva', 'salti')

sed la sekvaj manieroj estus nevalidaj:

papago() # necesa argumento mankas
papago(voltkvanto=5.0, 'morta') # ne-ŝlosilvorta arg-o
                                #sekvas ŝlosilvortan argo-n
papago(110, kvanto=220) # du valoroj por sama argumento
papago(actor='John Cleese') #nekonata ŝlosilvorto

Ĝenerale, en argumentaro, la ŝlosilvortaj argumentoj sekvas la poziciajn argumentojn. Ne gravas, se formala parametro havas implicitan valoron aŭ ne. Argumento ne povas ricevi valoron pli ol unufoje. Du argumentoj ne povas havi la saman nomon.

>>> def function(a):
...     pass
...
>>> function(0, a=0)
Traceback (most recent call last):
 File "<stdin>", line 1, in ?
TypeError: function() got multiple values for keyword argument 'a'

8.3. Arbitraj argumentaroj

Pitono permesas, ke oni povas prezenti nedifinitajn ŝlosilvortajn argumentojn kaj kromajn poziciajn argumentojn kiam oni vokas funkcion. Kiam la lasta formala parametro estas en la formo **nomo, ĝi ricevas vortaron kiu enhavas ĉiun ŝlosilvortan argumenton kies ŝlosilvorto ne egalas formala parametro. Kiam formala parametro estas en la formo *nomo, ĝi ricevas opon kiu enhavas poziciajn argumentojn preter la formala parametra listo (*nomo devas okazi antaŭ **nomo), ekz., se oni difinas funkcion jene:

>>> def fromaĝvendejo(tio, *argumentoj,**ŝlosilvort_argoj):
...     print "-- ĉu vi havas iom da", tio, '?'
...     print "-- Mi bedaŭras, ni ne havas", tio
...     for arg in argumentoj:
...         print arg
...     print '-'*40
...     keys = keywords.keys
...     keys.sort()
...     for kw in ŝlosilvort_argoj.keys():
...         print kw, ':', ŝlosilvort_argoj[kw]

Oni povas voki ĝin jene:

>>> fromaĝvendejo('Limburger', "Estas tre fluema, sinjoro.",
...     "Estas ja tre ege fluema, sinjoro.",
...     cliento='John Cleese',
...     vendisto='Michael Palin',
...     skizo='Fromaĝvendeja Skizo')

kaj ĝi videbligas, kompreneble:

-- ĉu vi havas iom da Limburger ?
-- Mi bedaŭras, ni ne havas Limburger
"Estas tre fluema, sinjoro.",
"Estas ja tre ege fluema, sinjoro.",
----------------------------------------
cliento : John Cleese
vendisto : Michael Palin
skizo : Fromaĝvendeja Skizo

Rimarku, ke la metodo sort() estas vokata antaŭ la presado de la vortaro. Se oni ne faras tion, la presordo estas nedifinita.

8.3.1. Malpaki argumentajn listojn

La mala situacio okazas kiam la argumentoj jam estas en listo aŭ opo, sed oni devas malpaki ilin por funkcio kiu postulas apartajn argumentojn. Ekzemple, la primitiva funkcio range() anticipas apartajn argumentojn ‘komencu’ kaj ‘haltu’. Oni povas uzi *-operacion por malpaki argumentojn el listo aŭ opo.

>>> args = [3,6]
>>> range(*args)
[3, 4, 5]

8.4. Dokumentaj ĉenoj

Aperas kutimoj pri la enhavo kaj formato de dokumentaraj ĉenoj

La unua linio ĉiam devus esti mallonga konciza resumo de la celo de la objekto. Ĝi ne devus eksplicite enhavi la nomon aŭ tipon de la objekto, ĉar tiuj estas havebla alimaniere (escepto estas, se la nomo estas verbo, kiu tiuj estas havebla alimaniere (escepto estas, se la nomo estas verbo, kiu litero, kaj fini per periodo.

Se ekzistas pluaj dokumentaj ĉenoj, la dua linio devus esti vaka, do vide apartigas la unuan linion kaj la ceteron de la priskribo. La sekvaj linioj devus esti unu aŭ pli alineoj priskribante la voko-konvenciojn, flankefikojn, ktp.

La unua non-vaka linio post la unua linio decidas la kvanton de marĝeno por la tuta dokumenta ĉenaro (Ni ne povas uzi la unuan linion, ĉar pro la citiloj, la vera marĝeno ne estas evidenta) spaceto “egala” al ĉi tiu marĝeno estos senigita el la komenco de ĉiu linio de la ĉeno. Linioj kiu havas malpli da marĝeno (ne devus okazi) devus esti senigita same. Oni devus testi la egalecon de spacetoj post grandigo de taboj (kutime al 4 spacetoj)

Jen ekzemplo:

>>> def my_function():
...     """Faru nenion, sed dokumentu ĝin.
...
...     Ne, fakte, ĝi faras nenion.
...     """
...     pass
...
>>> print my_function.__doc__
Faru nenion, sed dokumentu ĝin.

    Ne, fakte, gi faras nenion.