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.