terça-feira, 5 de outubro de 2010

Ovo Estrelado

No outro dia voltei ao passado quando almocei um dos meus pratos preferidos de miúdo: bife com batatas fritas e ovo estrelado. Soube-me bem e, em particular, o ovo estrelado estava óptimo. Quis saber como é tinha sido feito e o cozinheiro, entretanto chamado, prontificou-me a revelar o seu segredo. Para que seja eternizado, disse-me, vou escrever a receita numa folha de papel. No final deu-me a folha que dizia o seguinte:

RECEITA
Ovo Estrelado

Ingredientes: 1 ovo, óleo e sal q.b.
Material: fogão, frigideira, colher, prato

1- Coloque o óleo na frigideira e leve ao lume
2- Quando o óleo estiver quente, parta o ovo e deite-o na frigideira
3- Use a colher para regularmente deitar o óleo quente por cima do ovo
4- Quando tiver a consistência desejada, use a colher para o retirar da frigideira e coloque-o no prato.

Uns dias mais tarde, apeteceu-me comer um ovo estrelado e lembrei-me de usar a receita do restaurante. Fui buscar os ingredientes, preparei o material e retirei do bolso a receita que executei. No final, claro, comi o ovo!

Mas o que é que esta história tem a ver com a programação? Muito! É que programar é uma actividade que significa fundamentalmente escrever receitas (para resolver problemas), que alguém mais tarde vai usar. Vejamos como podemos explorar a analogia.

Em Python eu indico que vou escrever uma receita escrevendo a palavra reservada def. O nome da receita é nome da função. Os ingredientes são os parâmetros formais, isto é uma lista ordenada de nomes, separados por vírgulas e envolvidos por parêntesis. O material, são as eventuais constantes e nomes auxiliares criados pelo programa. Usar uma função significa (1) ligar os parâmetros reais aos parâmetros formais, processo esse que é feito quando chamamos (usamos) a função e, (2) executar as instruções da função. Do mesmo modo que na receita falamos em abstracto de um ovo, e quando realizamos a receita temos que usar um ovo concreto, também na programação os parâmetros formais são nomes genéricos, enquanto os parâmetros reais têm que remeter directa ou indirectamente para objectos. A ligação entre os parâmetros formais e os reais não é mais do que uma associação, ou seja uma instrução de atribuição implícita, entre o nome do parâmetro formal e o objecto para que remete o parâmetro real. Esta associação dura enquanto a função estiver a ser executada.

Um exemplo simples.

# Definição

def soma(x,y):
"""Calcula o valor da soma de x com y."""
return x + y

# Uso

a = 3
print soma(a,7)

Neste caso, o nome do programa é soma e os parâmetros formais são x e y. Chamamos a função usando o seu nome e os respectivos parâmetros reais. Neste caso, os parâmetros reais são o nome a (que está associado ao objecto 3) e o objecto 7. É como se tivesse-mos feito:

# Definição
def soma():
"""Calcula o valor da soma de x com y."""
x = a
y = 7
return x + y
# Uso
a = 3
print soma()

Porque devemos preferir sempre a primeira versão?? Pense um pouco e verá que a razão é simples!

Ao executar o código da função o resultado devolvido é, neste caso concreto, 10.

17 comentários:

  1. Professor, ao responder às perguntas de revisão das fichas surgiram me umas duvidas em termos de conceptualização da linguagem. Passo a explicar: em python, os objectos são caracterizados por ter três atributos: identidade, valor e tipo; ao fazermos uma atribuição estamos a fazer uma associção de um nome a um objecto, que passa a ser uma referencia para valor do mesmo; e por isso é justo dizermos que o nome é uma propriedade do objecto. No entanto, no acto da atribuicao tambem estamos a dar um valor a esse objecto. Como python tem mecanismo de DOCK TYPING(tipagem dinamica) o interpretador define logo um tipo para o objecto. Entao a minha duvida é: O tipo é propriedade do NOME ou do OBJECTO?

    ResponderEliminar
  2. Em Python o tipo é uma propriedade do objecto e não do nome, ao contrário de outras linguagens de programação. Por exemplo,

    >>> a = 5
    >>> a = 5.7

    Se não fosse assim o nome a não podia ficar associado a objectos de tipos diferentes.

    Este facto tem consequências muito importantes para a programação. quanto a mim é muito melhor assim!

    PS. Existe um bug no nome. É DUCK Typing, cuja filosofia é a de se algo grasna como um pato então é um pato!

    ResponderEliminar
  3. outra duvida: no momento em que estamos a definir uma definicao estamos, de forma identica a realizar o mesmo processo que numa atribuição: Estamos a associar um nome(o da definicao) a um objecto(que será o valor devolvido pela definicao)?

    ResponderEliminar
  4. E ao "usar" a definicao (chamando-a pelo nome) estamos a consultar o objecto a que associamos a definicao?

    ResponderEliminar
  5. Este comentário foi removido pelo autor.

    ResponderEliminar
  6. O nome da definição fica associado ao objecto que é toda a definição. Repare no sxeguinte:

    >>> def toto(n):
    ... n = n + 5
    ... return n
    ...
    >>> toto
    <function toto at 0x10154f0>
    >>> id(toto)
    16864496
    >>> type(toto)
    <type 'function'>
    >>>

    Se depois de definir a função, pergunta o que está associado ao nome toto, reparará que não é ao valor devolvido pela definição.

    ResponderEliminar
  7. Quando usa a definição acontecem duas coisas em sequência:

    (1) primeiro tem-se acesso, via nome, valor que nos dá a indicação de que se trata de uma função e do local onde se encontra o código;
    (2) sabido isto, manda-se executar o código. Veja listagem no comentário anterior.

    ResponderEliminar
  8. professor, quando nos é pedido para estabelecermos uma ligação entre o Espaço dos Objectos e o Espaço dos Nomes em que temos que ter maior atenção?
    A minha resposta seria com base na definição de cada um dos Espacos: Como o Espaco dos Nomes representa a zona da memoria onde se encontram os nomes associados aos objectos e o Espaco dos Objectos representa a zona da memoria em que os objectos são guardados, entao para lhes aceder utilizamos os nomes existentes para aceder aos objectos (funcionam como uma especie de apontadores de C).

    ResponderEliminar
  9. Professor, tenho 1ma dúvida, pode-se considerar o nome como um atributo de um objecto ou não?
    Obrigado

    ResponderEliminar
  10. O que liga o Espaço dos Nomes e o Espaço dos Objectos é realmente o conhecimento mútuo da identidade dos objectos.

    ResponderEliminar
  11. Não existem nomes que não estejam associados a objectos. Por outro lado um objecto pode ter vários nomes associados. Daqui resulta que os nomes são atributos dos objectos.

    ResponderEliminar
  12. Sim sim, eu percebo que existe uma partilha de identidade como resultado de uma associação, mas é isso condição suficiente para dizermos que um nome é atributo de um objecto?

    ResponderEliminar
  13. Repito: os nomes só existem em associação aos objectos. Não têm existência independente destes. Logo a ligação entre ambos é uma condição necessária à existência do nome. Não é um atributo no mesmo sentido que o são a identidade o valor e o tipo: um objecto pode existir sem nome!

    ResponderEliminar
  14. Professor, não estou a conseguir usar o turtle no meu computador, como faço para instala-lo? Já andeia pesquisar pela net mas nao encontro nada que me diga como o fazer.

    ResponderEliminar
  15. esqueça a minha pergunta, já sei, tava era a dar-me erro o código que tinha posto. Obrigado na mesma

    ResponderEliminar
  16. Ainda sobre o módulo turtle. Mesmo já tendo resolvido o problema, relembro a todos que para trabalhar com o módulo turtle este tem que ser importado antes de ser usado. Se for no interpretador fazer:

    >>> import turtle


    Se for num ficheiro, colocar o comando no ínicio.
    Existem outros módulos semelhantes que se podem obter a partir da net: cTurtle, xturtle. Para estes é necessário um processo especial de instalação que consiste, de um modo simples, em colocar o módulo na pasta site-packages.

    ResponderEliminar