Parâmetros de Função em Python
Uma função pode receber parâmetros. Através desses parâmetros, podemos passar dados para a função. Um exemplo simples é a função print(), que recebe um valor por meio de um parâmetro e o exibe no console.
Agora, vamos definir e utilizar uma função com parâmetros:
def say_hello(name):
    print(f"Hello, {name}")
say_hello("Tom")
say_hello("Bob")
say_hello("Alice")A função say_hello possui um parâmetro chamado name. Quando chamamos a função, podemos passar um valor para esse parâmetro. Dentro da função, o parâmetro é tratado como uma variável comum, e seu valor pode ser utilizado, como no exemplo em que o valor do parâmetro é exibido no console pela função print. Quando chamamos a função say_hello com diferentes valores, a função exibe uma mensagem diferente para cada chamada:
Hello, Tom Hello, Bob Hello, Alice
Os valores são passados aos parâmetros com base na posição. Vamos ver um exemplo de uma função com vários parâmetros:
def print_person(name, age):
    print(f"Name: {name}")
    print(f"Age: {age}")
print_person("Tom", 37)Aqui, a função print_person recebe dois parâmetros: name e age. Quando chamamos a função:
print_person("Tom", 37)O primeiro valor, "Tom", é atribuído ao parâmetro name, e o segundo valor, 37, é atribuído ao parâmetro age. O resultado no console será:
Name: Tom
Age: 37Valores Padrão
Podemos tornar alguns parâmetros opcionais, atribuindo-lhes valores padrão. Por exemplo:
def say_hello(name="Tom"):
    print(f"Hello, {name}")
say_hello()       # Aqui o parâmetro name será "Tom"
say_hello("Bob")  # Aqui name será "Bob"Nesse caso, o parâmetro name é opcional. Se não passarmos nenhum valor para ele ao chamar a função, o valor padrão "Tom" será utilizado. O resultado no console será:
Hello, Tom Hello, Bob
Se uma função tiver múltiplos parâmetros, os opcionais devem vir após os obrigatórios. Veja:
def print_person(name, age=18):
    print(f"Name: {name}  Age: {age}")
print_person("Bob")
print_person("Tom", 37)Aqui, o parâmetro age é opcional e tem o valor padrão de 18. Já o parâmetro name é obrigatório. O resultado será:
Name: Bob Age: 18 Name: Tom Age: 37
Também podemos tornar todos os parâmetros opcionais:
def print_person(name="Tom", age=18):
    print(f"Name: {name}  Age: {age}")
print_person()              # Name: Tom  Age: 18
print_person("Bob")         # Name: Bob  Age: 18
print_person("Sam", 37)     # Name: Sam  Age: 37Passando Valores por Nome (Parâmetros Nomeados)
Nos exemplos anteriores, os valores foram passados aos parâmetros pela ordem de posição. Contudo, também podemos passar valores aos parâmetros pelo nome, atribuindo o valor explicitamente ao nome do parâmetro:
def print_person(name, age):
    print(f"Name: {name}  Age: {age}")
print_person(age=22, name="Tom")Neste caso, estamos passando o valor 22 para o parâmetro age e "Tom" para o parâmetro name, mesmo que a ordem seja diferente da definida na função. O resultado será:
Name: Tom Age: 22
Parâmetros Nomeados com o Símbolo *
O símbolo * pode ser usado para definir quais parâmetros devem ser nomeados obrigatoriamente, ou seja, parâmetros que só podem ser passados por nome. Todos os parâmetros à direita do * devem ser nomeados:
def print_person(name, *, age, company):
    print(f"Name: {name}  Age: {age}  Company: {company}")
print_person("Bob", age=41, company="Microsoft")Aqui, age e company são parâmetros nomeados obrigatórios. O resultado será:
Name: Bob Age: 41 Company: Microsoft
Se quisermos que todos os parâmetros sejam nomeados, podemos colocar o * no início:
def print_person(*, name, age, company):
    print(f"Name: {name}  Age: {age}  Company: {company}")Parâmetros Posicionais Obrigatórios
Por outro lado, se desejarmos que alguns parâmetros sejam obrigatoriamente posicionais, podemos usar o símbolo /. Todos os parâmetros à esquerda de / devem ser passados pela posição:
def print_person(name, /, age, company="Microsoft"):
    print(f"Name: {name}  Age: {age}  Company: {company}")
print_person("Tom", company="JetBrains", age=24)
print_person("Bob", 41)Aqui, name é um parâmetro posicional. O resultado será:
Name: Tom Age: 24 Company: JetBrains Name: Bob Age: 41 Company: Microsoft
É possível combinar parâmetros posicionais e nomeados em uma única função:
def print_person(name, /, age=18, *, company):
    print(f"Name: {name}  Age: {age}  Company: {company}")
print_person("Sam", company="Google")
print_person("Tom", 37, company="JetBrains")
print_person("Bob", company="Microsoft", age=42)Aqui, o parâmetro name é posicional, e company é nomeado. O parâmetro age pode ser passado tanto por posição quanto por nome. O resultado será:
Name: Sam Age: 18 Company: Google Name: Tom Age: 37 Company: JetBrains Name: Bob Age: 42 Company: Microsoft
Quantidade Indefinida de Parâmetros
Podemos usar o símbolo * para indicar que uma função pode receber um número indefinido de valores. Isso é útil quando não sabemos quantos valores serão passados. Vamos ver um exemplo com uma função que soma números:
def sum(*numbers):
    result = 0
    for n in numbers:
        result += n
    print(f"sum = {result}")
sum(1, 2, 3, 4, 5)   # sum = 15
sum(3, 4, 5, 6)      # sum = 18Aqui, a função sum recebe um parâmetro *numbers. O * indica que podemos passar uma quantidade indefinida de valores. Dentro da função, utilizamos um laço for para iterar sobre os valores e calcular a soma.