8354
Comentário:
|
11189
|
Deleções são marcadas assim. | Adições são marcadas assim. |
Linha 1: | Linha 1: |
#pragma section-numbers off | |
Linha 3: | Linha 2: |
''' #E alguns Linguagismos Pythonicos sobre Funções em geral ;) ''' | ''' # E alguns Linguagismos Pythonicos sobre Funções em geral ;) ''' [[TableOfContents]] |
Linha 7: | Linha 8: |
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. |
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 este valor como argumento. Esse conceito foi introduzido na programação no final dos anos 50 pela linguagem Lisp, numa época 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. |
Linha 15: | Linha 16: |
As funções em Python são definidas atravez da palavra chave def. Sua sintaxe é a seguinte: | Antes de explorar os conceitos funcionais, vamos deixar os mecanismos de PYthon para criação e uso de funções bem claros. As funções em Python são definidas através da palavra chave def. Sua sintaxe é a seguinte: |
Linha 27: | Linha 30: |
#!python def foo(a=1, b=2): return a+b }}} ''Na função foo, a e b são argumentos não obrigatorios'' {{{ #!python def bar(a, b): 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. {{{ #!python def spam(x=[1, 2, 3]): if type(x) == list: 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). |
>>> def func(a,b='mundo',c='!'): ... print a, b, c ... >>> func('olá') olá mundo ! >>> func('olá', 'pessoal') olá pessoal ! >>> func() Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: func() takes at least 1 argument (0 given) }}} Quando houver mais de um argumento opcional na função e você quiser especificar apenas um ou mais deles, você pode chamar a função dizendo qual argumento você quer especificar: {{{ >>> func('adeus',c='?') adeus mundo ? }}} É possível declarar um argumento para pegar os parâmetros extras passados à função, precedendo-o com um asterisco: {{{ >>> def func(a,b='b',*args,**kwargs): ... print 'a = %s\nb = %s\nargs = %s\nkwargs = %s' % (a,b,args,kwargs) ... >>> func('a','c','d','e',par1='f',par2='g') a = a b = c args = ('d', 'e') kwargs = {'par2': 'g', 'par1': 'f'} }}} Note que foram declarados dois argumentos precedidos por asteriscos. O primeiro, precedido por um asterisco, irá receber os parâmetros extras passados em forma de tupla, e o segundo irá receber os parâmetros extras ''nomeados'' em forma de dicionário. Experimente outras variações no shell do python. |
Linha 58: | Linha 71: |
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. |
Ao contrário de algumas linguagens que não lhe permitem passar uma matriz como argumento, Python não faz restrições quanto a passar uma sequência (strings, listas, tuplas, unicodes) como argumento. {{{ #!python def spam(x=[1, 2, 3]): if isinstance(x, list): return "É possível passar uma lista como argumento em Python!" }}} 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 código. |
Linha 96: | Linha 112: |
=== "Side-Effects" === | Python permite que sejam criadas funções HighOrder, ou seja, uma funções que recebem como argumento ou retornam outras funções. Isso é especialmente interessante de ser usado em conjunto com @Decorators. {{{ #!python }}} == 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 variável de "transporte". {{{ #!python #Exemplo mais inútil impossível, mas espero que você pegue a idéia :) 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. Você pode usar um asterisco antes de um argumento na chamada da função para passar os argumentos da função atravez de uma lista. {{{ #!python #lembra do nosso cdr? cdr(*range(5)) }}} == "Side-Effects" == |
Linha 106: | Linha 146: |
side_effect() | our_double_a() |
Linha 111: | Linha 151: |
#!python | |
Linha 117: | Linha 158: |
#Se o que quisermos e apena imprimir o valor de retorno... | #Se o que quisermos e apenas imprimir o valor de retorno... |
Linha 122: | Linha 163: |
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. |
Evite Side-Effects em suas funções. Sua função fica mais difícil de se adivinhar o que faz do que se você retornasse um valor que pudesse ser explicitamente atribuído 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ões (maior reaproveitamento de código) Por exemplo, na nossa função "our_double_a" é difícil de imaginar que ela alteraria o valor de x. Além disso, ela fica limitada a isso: alterar o valor do nome x. Compare com a função our_double_b: fica claro quando eu estou alterando o valor de x ou não. |
Linha 131: | Linha 172: |
=== 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. |
== Recursão == Uma função que chama a si mesma é uma função recursiva. 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 paradigmas estruturados também 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 código poderia usar recursão. Certas linguagens funcionais, como Scheme, prevêem 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 código em um bloco separado?" e ele dirá algo como "Quando o código se repete". Mas quando o código 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 trouxer um melhor estilo. |
Linha 145: | Linha 191: |
== 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". {{{ #!python #Exemplo mais inutil impossivel, mas espero que você pegue a ideia :) 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. {{{ #!python #lembra do nosso cdr? cdr(*range(5)) }}} === Estilo === |
No livro capitulo 2.7 [http://www.paulgraham.com/lib/paulgraham/acl2.txt ANSI Common Lisp], ''Recursion'', PaulGraham diz: (livre tradução) '' (...) Muitas pessoas pessoas acham difícil a recurção no inicio. Muita dessa dificuldade vem do uso de uma metafora enganosa para funções. Há uma tendencia a pensar em funções como um tipo de maquinas. Matéria prima entra como os parâmetros; Algumas tarefas são repassadas para outras funções; finalmente o produto acabado é montado e entregue como o valor de retorno. se nós usarmos essa metáfora para funções, a recursão se torna um paradoxo. Como uma maquina pode enviar tarefas para ela mesma? Ela já esta ocupada.'' ''Uma melhor metáfora para a função seria pensar nela como um processo que se passa. Recursão é natural em um processo(...)'' == Closures == Python suporta Closures (ou [http://en.wikipedia.org/wiki/Closure_%28computer_science%29 lexical closures]) desde a versão 2.0, atravéz dos recurso de '''Nested Scopes'''. Exemplo: {{{#!python <exemplo> }}} == Estilo == |
Linha 181: | Linha 227: |
== Na Wiki: == | == Na Wiki == |
Linha 185: | Linha 231: |
UsandoGenerators |
|
Linha 191: | Linha 239: |
[http://c2.com/cgi/wiki?HigherOrderFunction C2 Wiki - Higher Order Function] [http://en.wikipedia.org/wiki/Python_programming_language#Functional_programming Python na Wikipedia - Seção Functional Programming] |
|
Linha 193: | Linha 245: |
* 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 :) |
* Adicionar mais exemplos! (de preferência tirados do UselessPython !!) * Mais exemplos, mais exemplos!!! De preferência, alguns úteis ou interessantes :) * Mais sobre HighOrder functions, quem sabe uma seção própria? * Concluir a seção sobre ''Closures'', com exemplos. * Citar e exemplificar o {{{lambda}}} * Uma seção somente com ''Exemplos Práticos''. |
Linha 197: | Linha 252: |
Linha 199: | Linha 255: |
---- ''Sugestão:'' Esta página fala na maior parte de particularidades das funções em python. Poderíamos mover este conteúdo para outra página (que poderia ser usada no NossoLivro) e deixar aqui apenas as coisas relativas à programação funcional. LuizCarlosGeron |
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 este valor como argumento.
Esse conceito foi introduzido na programação no final dos anos 50 pela linguagem Lisp, numa época 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
Antes de explorar os conceitos funcionais, vamos deixar os mecanismos de PYthon para criação e uso de funções bem claros.
As funções em Python são definidas através da palavra chave def. Sua sintaxe é a seguinte:
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.
>>> def func(a,b='mundo',c='!'): ... print a, b, c ... >>> func('olá') olá mundo ! >>> func('olá', 'pessoal') olá pessoal ! >>> func() Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: func() takes at least 1 argument (0 given)
Quando houver mais de um argumento opcional na função e você quiser especificar apenas um ou mais deles, você pode chamar a função dizendo qual argumento você quer especificar:
>>> func('adeus',c='?') adeus mundo ?
É possível declarar um argumento para pegar os parâmetros extras passados à função, precedendo-o com um asterisco:
>>> def func(a,b='b',*args,**kwargs): ... print 'a = %s\nb = %s\nargs = %s\nkwargs = %s' % (a,b,args,kwargs) ... >>> func('a','c','d','e',par1='f',par2='g') a = a b = c args = ('d', 'e') kwargs = {'par2': 'g', 'par1': 'f'}
Note que foram declarados dois argumentos precedidos por asteriscos. O primeiro, precedido por um asterisco, irá receber os parâmetros extras passados em forma de tupla, e o segundo irá receber os parâmetros extras nomeados em forma de dicionário. Experimente outras variações no shell do python.
Ao contrário de algumas linguagens que não lhe permitem passar uma matriz como argumento, Python não faz restrições quanto a passar uma sequência (strings, listas, tuplas, unicodes) como argumento.
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 código.
Retornando valores
Você também pode retornar qualquer objeto (até mesmo uma função) de uma função.
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.
Caso existam returns alinhados, no mesmo bloco, apenas o primeiro funcionará:
Python permite que sejam criadas funções HighOrder, ou seja, uma funções que recebem como argumento ou retornam outras funções. Isso é especialmente interessante de ser usado em conjunto com @Decorators.
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 variável de "transporte".
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.
Você pode usar um asterisco antes de um argumento na chamada da função para passar os argumentos da função atravez de uma lista.
"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.
Evite Side-Effects em suas funções. Sua função fica mais difícil de se adivinhar o que faz do que se você retornasse um valor que pudesse ser explicitamente atribuído 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ões (maior reaproveitamento de código)
Por exemplo, na nossa função "our_double_a" é difícil de imaginar que ela alteraria o valor de x. Além disso, ela fica limitada a isso: alterar o valor do nome x. Compare com a função our_double_b: fica claro quando eu estou alterando o valor de x ou não.
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
Uma função que chama a si mesma é uma função recursiva.
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 paradigmas estruturados também 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 código poderia usar recursão.
Certas linguagens funcionais, como Scheme, prevêem 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 código em um bloco separado?" e ele dirá algo como "Quando o código se repete". Mas quando o código 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 trouxer um melhor estilo.
No livro capitulo 2.7 [http://www.paulgraham.com/lib/paulgraham/acl2.txt ANSI Common Lisp], Recursion, PaulGraham diz: (livre tradução)
(...) Muitas pessoas pessoas acham difícil a recurção no inicio. Muita dessa dificuldade vem do uso de uma metafora enganosa para funções. Há uma tendencia a pensar em funções como um tipo de maquinas. Matéria prima entra como os parâmetros; Algumas tarefas são repassadas para outras funções; finalmente o produto acabado é montado e entregue como o valor de retorno. se nós usarmos essa metáfora para funções, a recursão se torna um paradoxo. Como uma maquina pode enviar tarefas para ela mesma? Ela já esta ocupada.
Uma melhor metáfora para a função seria pensar nela como um processo que se passa. Recursão é natural em um processo(...)
Closures
Python suporta Closures (ou [http://en.wikipedia.org/wiki/Closure_%28computer_science%29 lexical closures]) desde a versão 2.0, atravéz dos recurso de Nested Scopes.
Exemplo:
1 <exemplo>
Estilo
Procure usar o caracter \ para quebrar a linha e evitar linhas muito longas e ilegiveis. Exemplo:
Conclusão
Links
Na Wiki
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]
[http://c2.com/cgi/wiki?HigherOrderFunction C2 Wiki - Higher Order Function]
[http://en.wikipedia.org/wiki/Python_programming_language#Functional_programming Python na Wikipedia - Seção Functional Programming]
Por fazer:
Adicionar Links para trechos afins do DiveIntoPython, Thinking Like a Computer Scientist, etc
Adicionar mais exemplos! (de preferência tirados do UselessPython !!)
Mais exemplos, mais exemplos!!! De preferência, alguns úteis ou interessantes
Mais sobre HighOrder functions, quem sabe uma seção própria?
Concluir a seção sobre Closures, com exemplos.
Citar e exemplificar o lambda
Uma seção somente com Exemplos Práticos.
- Uma Conclusão
Sugestão: Esta página fala na maior parte de particularidades das funções em python. Poderíamos mover este conteúdo para outra página (que poderia ser usada no NossoLivro) e deixar aqui apenas as coisas relativas à programação funcional. LuizCarlosGeron