Os conceitos básicos sobre funções e procedimentos foram visto em Portugol: Funções e Portugol: Procedimentos na linguagem Portugol. A leitura é recomenda.

Procedimentos em Python, assim como em várias outra linguagens, são "funções" que não retornam nenhum tipo de valor ao término de sua execução.

Sintaxe
def nome_procedimento()
    corpo procedimento
Onde
def: palavra reservada que define uma procedimento ou função.

Para invocar um procedimento, utilizamo seu próprio nome no local desejado.

Exemplo 1
def nome_funcao():
    print("nome_funcao")
Saída
nome_funcao

Função diferente de procedimentos, retornam um valor durante a sua execução ou ao seu fim. Qualquer tipo de dado estudado dentre os já estudados pode ser utilizado como retorno.

Sintaxe
def nome_funcao():
	//omitido
    return valor_retorno
Onde
valor_retorno: valor que será retornado pela função.
return: Comando para retornar um valor de uma função
Exemplo 2
def nome_funcao():
    print("nome_funcao")
    return "uma string"

print(nome_funcao())
Saída
nome_funcao
uma string

Para a passagem de argumentos para funções em Python, semelhante a outras linguagens de programação, declaramos todos os parâmetros de acordo com a sintaxe abaixo:

Sintaxe
def nome_funcao(param1, param2, paramN) 
    #corpo_funcao
    return valor_retorno
Onde
valor_retorno: valor que será retornado pela função.
param1..N: lista de parâmetros separados por vírgula
Exemplo 3
def nome_funcao(param1, param2):
    print("param1:",param1)
    print("param2:",param2)
    return param1 + param2

print("retorno",nome_funcao(1,2))
Saída
param1: 1
param2: 2
retorno 3

Caso seja necessário passar uma grande quantidade de parâmetros, Python nos fornece o uso do operador "*", antes de um parâmetro definido, para informar que uma lista de parâmetros está sendo recebida pela função.

Sintaxe
def nome_funcao(*parametros) 
    #corpo_funcao
    return valor_retorno

Nesta sintaxe acima, *parametros será convertido para uma array/vetor e o acesso ao seu conteúdo deve ser feito utilizando o indexador [] ou utilizando algum comando de repetição.

Exemplo 4
def nome_funcao(*parametros):
    for p in parametros:
        print(p)

nome_funcao(1,2,3)
Saída
1
2
3

A linguagem python permite que a passagem de argumentos para funções seja feita utilizando seus respectivos nomes e valores. Dessa forma, independente da ordem dos argumentos passados, seus valores serão "casados" corretamente com seus respectivos parâmetros.

Sintaxe
def nome_funcao(param1=valor1, param2=valor2, paramN=valorN) 
    #corpo_funcao
    return valor_retorno
Exemplo 5
def nome_funcao(param1,param2):
    print(param1,param2);

nome_funcao(param1=1,param2=2)
nome_funcao(param2=2,param1=1)
Saída
1 2
1 2

A passagem de argumento por referencia e valor já foram visto em Portugol: Passagem de Argumento e em Tutorial C: Funções/Passagem de Argumento.

Quando simplesmente passamos um valor ou variável como argumento para uma função, estamos passando apenas seu valor. Depois de usado internamente na função, esse valor será destruído.

Exemplo 6
param1 = 10
def nome_funcao(param1):
    param1 = 100;

print("antes:",param1)
nome_funcao(param1)
print("depois",param1)
Saída
antes: 10
depois 10

Para passarmos um valor por referência, precisamos utilizar algum objeto no qual desejamos modificador seu conteúdo. Objetos e estruturas de dados dinâmicas como Tuple, Set e Dictonary podem ser utiilizados.

Exemplo 6.1
lista = [1,2]

def nome_funcao(param1):
    param1.append(4) # adição de novo elemento
    
print("antes:",lista)
nome_funcao(lista)
print("depois",lista)
Saída
antes: [1, 2]
depois [1, 2, 4]
Exemplo 6.2
def nome_funcao(param):
    param.atributo = 10
    
class classe:
  atributo = 0
#objeto
obj = classe()
obj.atributo = 1

print("antes:",obj.atributo)
nome_funcao(obj)
print("depois",obj.atributo)
Saída
antes: 1
depois 10

A linguagem Python não permite o retorno de múltiplos valores como em linguagens como Go e Lua, por exemplo. Para que uma função retorne mais de uma valor em Python, precisamos utilizar algum objeto ou estrutura de dados dinâmica.

Exemplo 7
class classe:
  atributo1 = 0
  atributo2 = 0
  
def nome_funcao():
    #objeto
    obj = classe()
    obj.atributo1 = 1
    obj.atributo2 = 2
    
    return obj

obj = nome_funcao();
print(obj.atributo1,obj.atributo2)
Saída
1 2

O assunto classe/objeto podem ser visto em sua respectiva seção Python: POO > CLASSE.

Como as funções escritas em Python não utilizam, por exemplo, { e } ou begin e end para informar o início e fim do corpo de uma função, a declaração de uma função em Python não pode ficar vazia para uma futura implementação. Nesses casos devemos usar o comando pass:

Sintaxe
def nome_funcao(parametros):
    pass
Exemplo 8
def nome_funcao1():
    pass

def nome_funcao2():
    pass
    
def nome_funcao3(p):
    print(p)

nome_funcao3(100)
Saída
100
  1. 18/09/2024 - revisão 1 - Correção em links portugol; ajustes gramaticais; remoção de tópico 'Argumentos nomeados' duplicado;
  2. 12/02/2024 - versão inicial