Já ouvimos várias vezes dizer que, em Python,
tudo são objectos. Por exemplo, os números (inteiros ou não), as cadeias de caracteres, as listas, os dicionários, os ficheiros, tudo isso são objectos. Dizem-nos, vezes sem conta, que esses objectos têm três atributos fundamentais: identidade, valor e tipo. Quando queremos usar esses objectos podemos usar referência explícitas, como quando calculamos:
Mas o mais usual é darmos um
nome ao objecto e passarmos a referir-mo-nos a esse objecto pelo seu nome:
1.
>>> a
=
5
2.
>>>
5
+
a
3.
10
4.
>>>
Sempre que usamos a
instrução de atribuição criamos uma nova
associação entre um nome e um objecto. É claro que um objecto pode ter vários nomes:
01.
>>> a
=
5
02.
>>> b
=
a
03.
>>> id(a)
04.
16793944
05.
>>> id(b)
06.
16793944
07.
>>> b
08.
5
09.
>>>
Mas o que se passa, quando definimos uma
função, como em:
1.
>>>
def
toto(x):
2.
...
return
2
*
x
3.
...
4.
>>>
Criamos na mesma um
objecto do tipo função:
1.
>>> type(toto)
2.
<type
'function'
>
3.
>>> id(toto)
4.
13426544
5.
>>> toto
6.
<function toto at
0xccdf70
>
7.
>>>
Neste caso a descrição do valor é mais complexa (
), mas não deixa de ser um objecto. Então pode também ter vários nomes como acontece com os outros tipos de objectos? Claro!
1.
>>> toto(
5
)
2.
10
3.
>>> tete
=
toto
4.
>>> tete(
5
)
5.
10
6.
>>>
Bom, mas então põe-se outra questão. Quando eu
defino algo, nessa definição posso ter
parâmetros formais, ou argumentos. Na altura de
usar o programa eu comunico quais os
parâmetros reais e estabeleço uma relação, temporária, entre eles:
1.
>>> a
=
5
2.
>>> toto(a)
3.
10
4.
>>>
Os parâmetros formais são
sempre nomes de objectos. Os parâmetros reais podem ser nomes, objectos ou expressões cujo valor é uma referência para um objecto.
No exemplo dado, o parâmetro formal
x da definição é associado ao parâmetro real
a, aquando do
uso da definição. Em termos práticos é como se, no início da execução do programa, se tivesse feito
x = a, sendo que essa associação é válida durante a execução do programa, caso não seja alterada por outra associação. Mas, e regressamos à questão,
será possível associar um parâmetro formal com uma definição? É possível:
01.
>>>
def
toto(x):
02.
...
print
x
03.
...
04.
>>>
def
main(f,x):
05.
... f(x)
06.
...
07.
>>> main(toto,
5
)
08.
5
09.
>>>
O que é que aconteceu? Bem, durante o
uso do programa
main, o parâmetro formal
f fica associado ao parâmetro real
toto. Então, quando tenho a instrução
f(x), durante a execução é como se tivesse
toto(5). Esta ao ser executada, cumpre o seu papel e imprime
5. Mas esta possibilidade tem algum interesse? Claro que tem. Durante as aulas demos vários exemplos de código, por exemplo, código envolvendo imagens, em que é tudo idêntico menos uma pequena parte. Podemos transformar essa parte, por abstracção, numa nova definição, tornando assim o programa mais geral, mais legível e, pelo menos partes dele, reutilizável:
01.
def
manipula_imagem(imagem, funcao_cor):
02.
03.
largura
=
imagem.getWidth()
04.
altura
=
imagem.getHeight()
05.
nova_imagem
=
cImage.EmptyImage(largura,altura)
06.
07.
for
coluna
in
range(largura):
08.
for
linha
in
range(altura):
09.
pixel
=
imagem.getPixel(coluna,linha)
10.
novo_pixel
=
funcao_cor(pixel)
11.
nova_imagem.setPixel(coluna,linha, novo_pixel)
12.
return
nova_imagem
Este programa, apresentado nas aulas, pega numa imagem e transforma cada um dos seus pixeis de acordo com uma dada função. Diferentes
funcao_cor, originam diferentes resultados:
01.
def
pixel_sepia(pixel):
02.
03.
r
=
pixel.getRed()
04.
g
=
pixel.getGreen()
05.
b
=
pixel.getBlue()
06.
07.
novo_r
=
(r
*
0.393
+
g
*
0.769
+
b
*
0.189
)
08.
novo_g
=
(r
*
0.349
+
g
*
0.686
+
b
*
0.168
)
09.
novo_b
=
(r
*
0.272
+
g
*
0.534
+
b
*
0.131
)
10.
if
novo_r >
255
: novo_r
=
r
11.
if
novo_g >
255
: novo_g
=
g
12.
if
novo_b >
255
: novo_b
=
b
13.
14.
novo_pixel
=
cImage.Pixel(novo_r,novo_g,novo_b)
15.
return
novo_pixel
16.
17.
def
pixel_cinzento(pixel):
18.
19.
vermelho
=
pixel.getRed()
20.
verde
=
pixel.getGreen()
21.
azul
=
pixel.getBlue()
22.
23.
int_media
=
(vermelho
+
verde
+
azul)
/
3
24.
novo_pixel
=
cImage.Pixel(int_media,int_media, int_media)
25.
return
novo_pixel
pixel_sepia e
pixel_cinzento são dois exemplos possíveis de funções de cor distintas.