Percursos
/
Python
Python
/
Programa
/
Argumentos de funções
Ar

Argumentos de funções em Python

{one: "1 exercício", many: "%{count} exercícios", other: "%{count} exercícios"}

Sobre Argumentos de funções

Para conheceres os fundamentos dos argumentos de funções, consulta o conceito de funções.

Nomes dos parâmetros

Os nomes dos parâmetros, tal como os nomes das variáveis, têm de começar por uma letra ou um underscore e podem conter letras, underscores ou números. Os nomes dos parâmetros não devem conter espaços nem pontuação.

Argumentos posicionais

Os argumentos posicionais são valores passados a uma função na mesma ordem dos parâmetros a que ficam associados. Opcionalmente, os argumentos posicionais podem ser passados usando o nome do parâmetro:

def concat(greeting, name):
    return f"{greeting}{name}"

# Passing data to the function by position.
print(concat("Hello, ", "Lilly"))
#->  Hello, Lilly

# Passing data to the function using the parameter name.
print(concat(name="Glenn", greeting="Hello, "))
#-> Hello, Glenn

A primeira chamada a concat passa os argumentos por posição. A segunda chamada a concat passa os argumentos por nome, o que permite alterar as suas posições.

Repara que os argumentos posicionais não podem vir depois de argumentos passados por nome (_também chamados argumentos nomeados. Não devem ser confundidos com parâmetros var-posicionais nem com **kwargs**).

Este conjunto de argumentos:

print(concat(greeting="Hello, ", "Gregor"))

Dá origem a este erro:

SyntaxError: positional argument follows keyword argument

Para exigir argumentos apenas posicionais nas chamadas a funções, podes usar o operador / na lista de parâmetros:

# Parameters showing a position-only operator. 
def concat(greeting, name, /):
    return f"{greeting}{name}"

print(concat("Hello, ", "Ginnie"))
#-> Hello, Ginnie

# Call to the function using keyword arguments.
print(concat(name="Franklin", greeting="Hello, "))
Traceback (most recent call last):
    print(concat(name="Franklin", greeting="Hello, "))
TypeError: concat() got some positional-only arguments passed as keyword arguments: 'greeting, name'

Argumentos nomeados

Os argumentos nomeados usam o nome do parâmetro ao chamar uma função. Podem, opcionalmente, ser indicados por posição:

def concat(greeting, name):
    return f"{greeting}{name}"

# Function call using parameter names as argument keywords.
print(concat(name="Eliza", greeting="Hello, "))
#-> Hello, Eliza

# Function call with positional data as arguments.
print(concat("Hello, ", "Tim"))
#-> Hello, Tim

Para exigir argumentos apenas nomeados nas chamadas a funções, podes usar o operador * na lista de parâmetros:

# Function definition requiring keyword-only arguments.
def concat(*, greeting, name):
    return f"{greeting}{name}"

# Keyword arguments can be in an arbitrary order.
print(concat(name="Kimmie", greeting="Hello, "))
#-> Hello, Kimmie

# Calling the function with positional data raises an error.
print(concat("Hello, ", "Coleen"))
Traceback (most recent call last):
    print(concat("Hello, ", "Coleen"))
TypeError: concat() takes 0 positional arguments but 2 were given

Valores por omissão dos argumentos

Os valores por omissão de um ou mais argumentos podem ser indicados na lista de parâmetros. Isto permite chamar a função com menos argumentos, se for preciso. Os valores por omissão podem ser substituídos chamando a função com um novo valor de argumento:

# Function with default argument values.
def concat(greeting, name="you", punctuation="!"):
    return f"{greeting}, {name}{punctuation}"

print(concat("Hello"))
#-> Hello, you!

# Overriding the default values
print(concat("Hello", name="Polly", punctuation="."))
#-> Hello, Polly.

Argumentos posicionais ou nomeados

Os argumentos podem ser posicionais ou nomeados se não se usarem os operadores / nem * nas definições dos parâmetros. Em alternativa, os argumentos posicionais ou nomeados podem ser colocados entre os parâmetros apenas posicionais, à esquerda, e os parâmetros apenas nomeados, à direita:

# Position-only argument followed by position-or-keyword, followed by keyword-only.
def concat(greeting, /, name, *, ending):
    return f"{greeting}{name}{ending}"

print(concat("Hello, ", "Mark", ending="!"))
#-> Hello, Mark!

print(concat("Hello, ", name="Rachel", ending="!"))
#-> Hello, Rachel!

print(concat(greeting="Hello, ", name="JoJo", ending="!"))
Traceback (most recent call last):
    print(concat(greeting="Hello, ", name="JoJo", ending="!"))
TypeError: concat() got some positional-only arguments passed as keyword arguments: 'greeting'

*args

Os exemplos de código usam frequentemente uma definição de função parecida com a seguinte:

def my_function(*args, **kwargs):
    # code snipped

*args é um nome com duas partes que representa um tuple com um número indefinido de argumentos posicionais separados, também conhecido como variadic argument. args é o nome dado ao tuple de argumentos, mas podia ser qualquer outro nome válido em Python, como my_args, arguments, etc. O * é o operador que transforma o conjunto de argumentos separados num tuple.

Note

Se já alguma vez desempacotaste um tuplo, podes achar confuso o * em *args. O * numa definição de parâmetro, em vez de desempacotar um tuplo, converte um ou mais argumentos posicionais num tuplo.

Dizemos que o operador * está sobrecarregado, pois tem comportamentos diferentes em contextos diferentes. Por exemplo, o * é usado para a multiplicação, é usado para desempacotar e é usado para definir um número arbitrário de parâmetros posicionais.

Como é possível iterar sobre um tuple, o args pode ser passado a qualquer outra função que aceite um iterável. Embora o *args apareça frequentemente associado ao **kwargs, não tem de ser assim:

def add(*args):
    # args is passed to the sum function, which iterates over it.
    return sum(args)

print(add(1, 2, 3))
#-> 6

Se o *args vier depois de um ou mais argumentos posicionais, então o *args será o que sobra depois desses argumentos posicionais:

def add(first, *args):
    # first will be 1, leaving the values 2 and 3 in *args
    return first + sum(args)

print(add(1, 2, 3))
#-> 6

Se um ou mais argumentos por omissão forem definidos depois do *args, ficam separados dos valores do *args:


def add(first, *args, last=0):
    return first + sum(args) + last
 
print(add(1, 2, 3))
#-> 6

print(add(1, 2, 3, last=4))
#-> 10

# This uses the unpacking operator * to separate the list elements into positional arguments.
# It does not have the same behavior as the * (packing) in *args.
print(add(*[1, 2, 3]))
#-> 6

Repara que, quando um argumento já está dentro de um iterable (como um tuple ou uma list), é preciso desempacotá-lo antes de o passar a uma função que aceita um número arbitrário de argumentos separados. Isto faz-se com o *, que é o operador de desempacotamento.

Neste contexto, o * desempacota o contentor nos seus elementos separados, que depois são transformados pelo *args num tuple. Quando só há argumentos posicionais, a operação de desempacotamento tem de dar origem ao mesmo número de argumentos que os parâmetros formais definidos.

Sem desempacotar a lista passada a add, o programa daria erro:

def add(first, *args, last=0):
    return first + sum(args) + last

print(add([1, 2, 3]))
Traceback (most recent call last):
    print(add([1, 2, 3]))
    return first + sum(args) + last
TypeError: can only concatenate list (not "int") to list

**kwargs

**kwargs é um nome com duas partes que representa um número indefinido de pares chave-valor distintos como argumentos. kwargs é o nome do conjunto de argumentos e podia ser qualquer outro nome, como my_args, arguments, etc. O ** transforma o conjunto de argumentos nomeados num dictionary de pares {argument name: argument value}.

Como é possível iterar sobre um dicionário, o kwargs pode ser passado a qualquer outra função que aceite um iterável. Embora o **kwargs apareça frequentemente associado ao *args, não tem de ser assim:

def add(**kwargs):
    return sum(kwargs.values())

print(add(one=1, two=2, three=3))
#-> 6

Repara que o método dict.values() é chamado para iterar sobre os values do dicionário kwargs. Ao iterar sobre um dicionário, o comportamento por omissão é iterar sobre as keys, por isso é preciso indicar dict.values() explicitamente:

def concat(**kwargs):
    # Join concatenates the tuples from `kwargs.items()`
    return " ".join((str(item) for item in kwargs.items()))

print(concat(one=1, two=2, three=3))
#-> ('one', 1) ('two', 2) ('three', 3)
Editar via GitHub A ligação abre numa nova janela ou separador