• Nenhum resultado encontrado

Passagem de parâmetros

No documento Python e Django Fundamentos (páginas 58-63)

q

1 Podemos fornecer valores padrão para parâmetros.

1 Na passagem de parâmetros, é possível indicar o nome do parâmetro, que são cha- mados de keyword arguments.

1 Existe uma sintaxe para passar um número variável de parâmetros e keyword arguments. 1 Os argumentos podem ser desempacotados na chamada de funções.

Dica: para retornar ao interpretador, é necessário pressionar a tecla “q”.

Ca pí tu lo 2 - O ut ro s t ip os d e d ad os , e st ru tu ra s d e c on tr ol e e f un çõ es

Os parâmetros das funções em Python podem ter valores padrão. Os parâmetros que não possuem valor padrão são obrigatórios. Quando executamos a função, podemos usar o nome do parâmetro para fornecer o seu valor. Caso o nome do parâmetro não seja forne- cido, é necessário respeitar a ordem em que foram definidos. Caso o nome do parâmetro seja fornecido, a ordem de passagem de parâmetros pode ser alterada. Chamamos os parâmetros nomeados de “keyword arguments”. Existe uma sintaxe para passagem de uma quantidade variável de parâmetros e quantidade variável de argumentos nomeados. Também é possível desempacotar um conjunto de valores na passagem de parâmetros durante a execução da função.

src/modelo16.txt

>>> def potenciacao(base, expoente=2): # (1) ... resultado = base ** expoente

... return resultado ... >>> potenciacao(2) # (2) 4 >>> potenciacao(3, 3) # (3) 27 >>> def somatorio(*args): # (4) ... resultado = 0

... for numero in args: # (5) ... resultado += numero ... return resultado ... >>> somatorio(1,2) 3 >>> somatorio(1,2,4,8,16) 31

1 # (1): quando definimos uma função, inicializamos o valor padrão de um argumento. 1 # (2): na execução da função, não é necessário fornecer o valor do argumento que possui

valor padrão.

1 # (3): ao fornecer um argumento, o valor padrão é sobrescrito.

1 # (4): a técnica de empacotamento e desempacotamento de tuplas permite definir funções que recebem número indefinido de argumentos. Usa-se um asterisco para definir um argumento que receberá uma tupla.

1 # (5): podemos então percorrer a tupla para utilizar os valores dos argumentos.

#!/usr/bin/env python3 # src/modelo17.py """

>>> item = {'Calça jeans': 1}

>>> compras_cliente1 = lista_de_compras(item) >>> compras_cliente1

P yt ho n e D ja ng o F un da m en to s [{'Calça jeans': 1}] >>> item = {'Camiseta': 1} >>> lista_de_compras(item, compras_cliente1) [{'Calça jeans': 1}, {'Camiseta': 1}] >>> item = {'Bermuda': 1}

>>> compras_cliente2 = lista_de_compras(item) >>> compras_cliente2

[{'Calça jeans': 1}, {'Camiseta': 1}, {'Bermuda': 1}] """

def lista_de_compras(item, compras=[]): compras.append(item)

return compras

Um cuidado especial precisa ser tomado quando definimos uma função que recebe um parâmetro lista com valor padrão. A lista é um tipo mutável, criada no momento da decla- ração da função e que continuará existindo enquanto a função existir. Nos exemplos, podemos perceber que a lista vai acumulando os itens, mesmo quando é esperado que uma nova lista seja criada. Os itens do cliente2 são adicionados na lista de compras do cliente1. O fato é que elas são a mesma lista.

#!/usr/bin/env python3 # src/modelo18.py """

>>> item = {'Calça jeans': 1}

>>> compras_cliente1 = lista_de_compras(item) >>> compras_cliente1

[{'Calça jeans': 1}] >>> item = {'Camiseta': 1}

>>> lista_de_compras(item, compras_cliente1) [{'Calça jeans': 1}, {'Camiseta': 1}] >>> item = {'Bermuda': 1}

>>> compras_cliente2 = lista_de_compras(item) >>> compras_cliente2

[{'Bermuda': 1}] """

def lista_de_compras(item, compras=None): if compras is None:

compras = [] compras.append(item) return compras

Para evitar o comportamento anterior, usa-se a seguinte técnica:

1 # (1): declaramos o argumento lista com o valor padrão None, o nulo da linguagem Python. 1 # (2): verificamos se o valor do argumento é None; se for, inicializamos uma lista vazia.

Ca pí tu lo 2 - O ut ro s t ip os d e d ad os , e st ru tu ra s d e c on tr ol e e f un çõ es

Agora, quando é criada a lista de compras do cliente2, de fato é criada uma nova lista, como é o esperado.

src/modelo19.txt

>>> def insere_elementos_lista(*args, valores=None): ... if valores is None:

... valores = [] ... for elemento in args: ... valores.append(elemento) ... return valores

...

>>> meus_elementos = []

>>> # Sem nomear o parâmetro, todos são empacotados em args. ... insere_elementos_lista(1, 2, 3, 4, 5, meus_elementos) [1, 2, 3, 4, 5, []]

>>> meus_elementos []

Outro cuidado que precisa ser tomado quando declaramos a tupla de argumentos (*args) é que todos os argumentos não nomeados explicitamente são empacotados. No exemplo, a lista meus_elementos é tratada como um argumento empacotado em *args e é adicionada como um item na lista valores.

src/modelo20.txt

>>> # A lista é mutável, então o conteúdo é mantido após o

... # término da função. ... insere_elementos_lista(1, 2, 3, 4, 5, valores=meus_elementos) [1, 2, 3, 4, 5] >>> meus_elementos [1, 2, 3, 4, 5] >>> insere_elementos_lista(6, 7, 8, 9, valores=meus_elementos) [1, 2, 3, 4, 5, 6, 7, 8, 9] >>> meus_elementos [1, 2, 3, 4, 5, 6, 7, 8, 9]

>>> # Para evitar isso, deixar o parâmetro vazio e atribuir o

... # resultado para a lista meus_elementos.

... meus_elementos = insere_elementos_lista(1, 2, 3, 4, 5) >>> meus_elementos [1, 2, 3, 4, 5] >>> meus_elementos = insere_elementos_lista(6,7,8) >>> meus_elementos [6, 7, 8] >>>

Quando as listas são alteradas dentro da função, elas permanecem alteradas após a exe- cução da função. Uma das maneiras de evitar isso é deixar de informar o argumento lista e atribuir o resultado à lista que vai guardar o resultado da função.

P yt ho n e D ja ng o F un da m en to s src/modelo21.txt >>> def listar_musica( ... nome, genero='Rock',

... subgenero='Clássico', artista='Led Zeppelin'): ... print('Música: ', nome, ', ', genero, ', ', ... subgenero, ', ', artista, sep='') ...

>>> listar_musica('Stairway to heaven')

Música: Stairway to heaven, Rock, Clássico, Led Zeppelin >>> listar_musica(nome='Whole Lotta Love') # (1) Música: Whole Lotta Love, Rock, Clássico, Led Zeppelin >>> listar_musica(

... nome='Travelling Riverside Blues', ... subgenero='Blues')

Música: Travelling Riverside Blues, Rock, Blues, Led Zeppelin >>> listar_musica(

... artista='Pink Floyd',

... nome='Wish You Were Here') # (2)

Música: Wish You Were Here, Rock, Clássico, Pink Floyd >>> listar_musica('Time', 'Rock', 'Clássico', 'Pink Floyd') Música: Time, Rock, Clássico, Pink Floyd

>>> listar_musica('Money', artista='Pink Floyd') # (3) Música: Money, Rock, Clássico, Pink Floyd

>>>

Quando for preciso, podemos utilizar o nome do argumento na execução da função. 1 # (1): definimos a função com argumentos que possuem valor padrão, então podemos

omitir alguns argumentos e usar o nome do argumento para informar um valor diferente do valor padrão.

1 # (2): ao usar o nome do argumento, podemos usar qualquer ordem.

1 # (3): só precisamos respeitar a ordem se for informado um argumento sem nome, passamos todos os argumentos sem nome que quisermos e depois podemos passar os argumentos nomeados.

src/modelo22.txt

>>> def monta_pizza(nome, *args, **kwargs): ... print('Pizza: ', nome)

... print('Ingredientes: ', end='') ... for ingrediente in args:

... print(ingrediente, ' ', end='') ... print() # Nova linha.

... print('-' * 20)

... print('Opcionais: ', end='') ... chaves = sorted(kwargs.keys()) ... for chave in chaves:

Ca pí tu lo 2 - O ut ro s t ip os d e d ad os , e st ru tu ra s d e c on tr ol e e f un çõ es

... print(chave, '=', kwargs[chave], ' ', end='') ... print() # Nova linha.

...

>>> monta_pizza('portuguesa', 'cebola', 'ovo', ... 'presunto', 'queijo', 'orégano', ... borda='cheddar', massa='integral', ... espessura='fina')

Pizza: portuguesa

Ingredientes: cebola ovo presunto queijo orégano ---

Opcionais: borda = cheddar espessura = fina massa = integral >>>

... Continua.

O exemplo anterior mostra como pode ser feito o desempacotamento de número indefinido de argumentos posicionais na tupla *args, assim como um número indefinido de argu- mentos nomeados no dicionário **kwargs. No código da função, basta tratar o argumento args como tupla e o argumento kwargs como dicionário. Além disso, usar um asterisco na declaração de args e dois asteriscos na declaração de kwargs.

src/modelo22.txt - continuação.

>>> ingredientes = ('cebola', 'ovo', 'presunto', ... 'queijo', 'orégano')

>>> opcoes = {'borda': 'cheddar', 'massa': 'integral', ... 'espessura': 'fina'}

>>> monta_pizza('portuguesa', *ingredientes, **opcoes) Pizza: portuguesa

Ingredientes: cebola ovo presunto queijo orégano ---

Opcionais: borda = cheddar espessura = fina massa = integral >>>

Considerando a mesma função definida no exemplo anterior, podemos desempacotar argu- mentos. Para isso, basta definir uma tupla e um dicionário. Ao executar a função, desempa- cota-se a tupla utilizando um asterisco e o dicionário usando dois asteriscos.

No documento Python e Django Fundamentos (páginas 58-63)