associação pythonbrasil[11] django zope/plone planet Início Logado como (Entrar)

Diferenças para "PrincipiosFuncionais"

Diferenças entre as versões de 5 e 6
Revisão 5e 2005-03-28 15:24:21
Tamanho: 8364
Comentário: ultimas 3 alteracoes:u
Revisão 6e 2005-03-28 15:39:26
Tamanho: 8365
Comentário:
Deleções são marcadas assim. Adições são marcadas assim.
Linha 106: Linha 106:
side_effect() our_double_a()

Principios da Programação Funcional em Python

#E alguns Linguagismos Pythonicos sobre Funções em geral ;)

Introdução

O conceito de funções em programação vem da matemática. Uma função serve para relacionar um conjunto (chamado de domínio) a outro (Imagem). Em programação, o domínio de uma função seriam os valores que pode-se passar como argumentos, e a Imagem é o conjunto dos possíveis valores de retorno. Para cada elemento no conjunto Domínio, deve haver apenas um elemento correspondente no conjunto imagem. Em programação funcional (e na matemática) esse é o princípio de idempotência, ou seja, para determinado valor de argumento só há uma possibilidade de retorno a cada vez que se passar um determinado valor como argumento.

Esse conceito foi introduzido na programação no final dos anos 50 pela linguagem Lisp, numa epoca em que a linguagem de mais alto nível que existia era o primeiro Fortran. Muitas linguagens desde então sofreram algum tipo de influência de Lisp e seus idiomas, direta ou indiretamente. Inclusive Python, que, por exemplo, tem um tipo função.

Segundo o artigo da Wikipedia [http://en.wikipedia.org/wiki/Python_programming_language#Philosophy Python programming language - seção "Philosophy"], Python é uma linguagem multiparadigma. Então por que não aprender mais um? :)

Definindo Funções em Python

As funções em Python são definidas atravez da palavra chave def. Sua sintaxe é a seguinte:

   1 def NomeDaFuncao(arg1, arg2, argn):
   2     <codigo>
   3     return NomeDoObjetoARetornar

Argumentos

Em Python, os argumentos podem ou não ter um valor inicial. Quando se dá um valor inicial na definição, não é obrigatório passar nenhum valor para esse argumento na chamada da função.

   1 def foo(a=1, b=2):
   2     return a+b

Na função foo, a e b são argumentos não obrigatorios

   1 def bar(a, b):
   2     return a+b

Na função bar, a e b são argumentos obrigatorios

Em Python, ao contrário de algumas linguagens que não lhe permitem passar uma matriz como argumento, não há restrições quanto a passar uma sequencia (strings, listas, tuplas, unicodes) como argumento.

   1 def spam(x=[1, 2, 3]):
   2     if type(x) == list:
   3         return "É possivel passar uma lista como argumento em Python!"

Você também pode definir um argumento precedido de um * (asterisco), para "capturar" o resto dos argumentos numa tupla (Ficando uma função com número de argumentos variavel).

   1 # Esta função é levemente semelhante ao "cdr" do lisp, mas o cdr do Lisp recebe uma lista
   2 # Esta recebe o que seriam os elementos da lista
   3 def cdr(arg1, *argN):
   4     "Retorna tupla com os argumentos, excluindo o primeiro"
   5     return argN

Você pode, ainda, usar ** antes de um argumento na definição da função. #Explicar esse truque! preciso de uma explicação melhor!

<exemplos>

Você pode ainda se aproveitar do polimorfismo da linguagem e permitir que sejam passados "tipos afins", como tipos que podem ser usados numa iteração, e não só um tipo, como lista por exemplo, aumentado a possibilidade de reuso do codigo.

Retornando valores

Você também pode retornar qualquer objeto (até mesmo uma função) de uma função.

   1 def RetornaFuncao(x=type):
   2     return x
   3 
   4 RetornaFuncao()(list)

Nesse exemplo, a ultima linha deve retornar <type 'type'>, por que list é um tipo

Sua função pode ainda ter varias vezes a palavra return.

   1 def isDead(parrot):
   2     "Retorna True se parrot avaliar como False"
   3     if not obj:
   4         return True
   5     else:
   6         return False

Caso existam returns alinhados, no mesmo bloco, apenas o primeiro funcionará:

   1 def DoisReturns(x, y):
   2     return x
   3     return y

"Side-Effects"

"Side-Effect", ou algo como 'efeito colateral', é um termo usado para indicar que uma função faz uma operação "destrutiva" , ou seja, ela altera, por exemplo, o valor de um objeto global, ou faz alguma operação de IO.

   1 x = 1
   2 def our_double_a():
   3     global x
   4     x += x
   5 
   6 our_double_a()
   7 print x
   8 #Isso deve imprimir 2 n tela

   1 def our_double_b(y):
   2     y += y
   3     return y
   4 #Se o que quisermos e apenas alterar o valor de x...
   5 x = 1
   6 x = our_double_b(x)
   7 #Se o que quisermos e apena imprimir o valor de retorno...
   8 x = 1
   9 print our_double_b(x)

Evite Side-Effects em suas funções. Sua função fica mais dificil de se adivinhar o que faz do que se você retornasse um valor que fosse explicitamente atribuido a um nome. Procure usar sempre os argumentos e os returns. Seguindo essa regra suas funções serão inclusive mais uteis em outras ocasiõea (maior reaproveitamento de codigo)

Por exemplo, na nossa funcao "our_double_a" e dificil de imaginar que ela alteraria o valor de x. Alem disso, ela fica limitada a isso, alterar o valor do nome x.Compare com a funcao our_double_b: fica claro quando eu estou alterando o valor de x ou nao.

Se você realmente pretende fazer uma função que tem Side-Effects, deixe isso bem claro no nome (adicionando um prefixo "set" e o que ele "seta", com "setName", por exemplo) e na docstring da função.

<exemplo>

Recursão

Muitas pessoas acham extremamente complicado aplicar o conceito de recursão, muitos alunos de programação não conseguem desenvolver algoritmos recursivos sem gastar **muito** grafite e papel antes. Muitos programadores acostumados com paradgmas extruturados tamb tem essa dificuldade, A maioria dos programadores evitam implementações recursivas de seus algoritmos, por motivos de performance também, mas muitas vezes nem percebemos que um codigo poderia usar recursão. Certas linguagens funcionais, como Scheme, preveem até mesmo que seus interpretadores tenham algum tipo de otimização de recursão. Pergunte a um estudante dedicado de programação "Quando colocar um trecho de codigo em um bloco separado?" e ele dirá algo como "Quando o codigo se repete". Mas quando o codigo se repete sucessivamente, normalmente usamos for ou while. Quando não houverem grandes problemas para a performance, a recursão pode valer a pena se trousser um melhor estilo.

   1 def factorial(x):
   2     if x == 0:
   3         return 1
   4     else:
   5         return x * factorial(x-1)

Chamadas de Função

Na hora de chamar uma função, você pode passar como argumento outra chamada de função, e será passado o valor de retorno dessa. Assim os valores fluirão de uma função para outra, sem necessidade uma variavel de "tranporte".

   1 #Exemplo mais inutil impossivel, mas espero que você pegue a ideia :)
   2 range(sum([0, 1, 2]))

Entre outras coisas "pensar funcionalmente" pode ser definido assim: projetar algoritmos onde os valores fluem do retorno de uma função para a chamada de outra.

Voce pode usar um asterisco antes de um argumento na chamada da função para passar os argumentos da função atravez de uma lista.

   1 #lembra do nosso cdr?
   2 cdr(*range(5))

Estilo

Procure usar o caracter \ para quebrar a linha e evitar linhas muito longas e ilegiveis. Exemplo:

   1 function1(\
   2           function11("foo"),\
   3           function12(\
   4                      function121(1, "bar"),\
   5                      function122("foobar")),\
   6           function13(84))

Conclusão

Links

Na Wiki:

PythonFuncional

ProgramacaoFuncional

No resto da Web

[http://diveintopython.org/functional_programming/index.html Dive into Python - Chapter 16. Functional Programming]

[http://en.wikipedia.org/wiki/Python_programming_language#Functional_programming Wikipedia - Python programming language - Functional programming]

Por fazer:

  • Adicionar Links para trechos afins do DiveIntoPython, Thinking Like a Computer Scientist, etc

  • Adicionar mais exemplos! (de preferencia tirados do UselessPython !!)

  • Links para essays do PaulGraham onde ele cita Python

  • Mais exemplos, mais exemplos!!! De preferencia, alguns uteis ou interessantes :)

  • Uma Conclusão


EduardoDeOliveiraPadoan