Como usar a passagem de referência em Python
Passagem por referência em Python: Contexto e Melhores Práticas
por Marius Mogyorosi (intermediário) python
Após adquirir familiaridade com Python, você pode perceber casos em que suas funções não modificam os argumentos como o esperado, especialmente se estiver familiarizado com outras linguagens de programação. Algumas linguagens tratam os argumentos de função como referências a variáveis existentes, o que é conhecido como passagem por referência. Outras linguagens os tratam como valores independentes, uma abordagem conhecida como passagem por valor.
Se você é um programador Python intermediário que deseja entender a maneira peculiar do Python de lidar com os argumentos de função, então este tutorial é para você. Você implementará casos de uso reais de construções de passagem por referência em Python e aprenderá várias melhores práticas para evitar armadilhas com seus argumentos de função.
Neste tutorial, você aprenderá:
- O que significa passagem por referência e por que você gostaria de usá-la.
- Como a passagem por referência difere tanto da passagem por valor quanto da abordagem única do Python.
- Como os argumentos de função se comportam em Python.
- Como você pode usar certos tipos mutáveis para passar por referência em Python.
- Quais são as melhores práticas para replicar a passagem por referência em Python.
Definindo Passagem por Referência
Antes de mergulharmos nos detalhes técnicos da passagem por referência, é útil dar uma olhada mais de perto no próprio termo, dividindo-o em componentes:
- Passar significa fornecer um argumento para uma função.
- Por referência significa que o argumento que você está passando para a função é uma referência a uma variável que já existe em memória, em vez de uma cópia independente dessa variável.
Como você está fornecendo à função uma referência a uma variável existente, todas as operações realizadas nessa referência afetarão diretamente a variável à qual ela se refere. Vamos ver alguns exemplos de como isso funciona na prática.
Abaixo, você verá como passar variáveis por referência em C#. Observe o uso da palavra-chave ref
nas linhas destacadas:
C#
No exemplo acima, a função ModifyByReference
recebe uma referência para a variável inteira arg
, que é modificada para o valor 10 dentro da função. Essa modificação afeta diretamente a variável arg
fora da função ModifyByReference
.
Comparando Passagem por Referência e Passagem por Valor
A passagem por referência é diferente da passagem por valor, pois a passagem por referência lida com as referências às variáveis, enquanto a passagem por valor lida com as cópias independentes das variáveis. Vamos comparar os dois métodos:
- Passagem por Valor: Quando você passa um argumento por valor, uma cópia independente desse argumento é criada. Qualquer modificação feita nessa cópia não afetará o valor original do argumento.
- Passagem por Referência: Quando você passa um argumento por referência, você está passando uma referência à variável original. Qualquer modificação feita na referência afetará diretamente o valor original da variável.
Em Python, a passagem de argumentos para funções é diferente de ambos os métodos mencionados acima. Python possui seu próprio modo único de tratar os argumentos de função, o qual exploraremos nas seções a seguir.
Utilizando Construções de Passagem por Referência
Agora que você entendeu os conceitos básicos da passagem por referência, vamos explorar algumas maneiras de implementar a passagem por referência em Python.
Evitando Objetos Duplicados
Uma das vantagens de utilizar a passagem por referência é evitar a criação de objetos duplicados. Em Python, quando você passa um objeto mutável como argumento para uma função, você está passando uma referência ao objeto original. Isso significa que qualquer modificação feita na referência dentro da função afetará diretamente o objeto original.
No exemplo acima, a função modify_list
recebe uma referência à lista my_list
e adiciona o número 4 a ela. Como a referência é uma referência direta à lista original, a lista modificada é impressa corretamente.
Retornando Múltiplos Valores
Outra forma de utilizar a passagem por referência em Python é retornando múltiplos valores de uma função. Em vez de retornar os valores separadamente, você pode retornar uma única estrutura de dados que contenha todos os valores desejados.
No exemplo acima, a função calculate_statistics
recebe uma lista de números e retorna um dicionário contendo as estatísticas desses números. Ao retornar o dicionário como um todo, é possível acessar todos os valores de estatísticas em um único objeto.
Criando Funções com Múltiplos Retornos Condicionais
Em alguns casos, pode ser útil retornar múltiplos valores de uma função com base em condições específicas. Em vez de criar várias funções para lidar com cada condição, você pode usar a passagem por referência para retornar os valores condicionais diretamente para as variáveis de destino.
No exemplo acima, a função get_user_info
verifica se um usuário existe no banco de dados com base em um ID fornecido. Ela retorna uma variável booleana exists
, que indica se o usuário existe ou não, e um dicionário data
contendo os dados do usuário. Ao atribuir os retornos da função diretamente às variáveis exists
e data
, você pode utilizá-las de acordo com as necessidades específicas.
Passando Argumentos em Python
Em Python, a passagem de argumentos para funções segue um processo específico. Para entender melhor, vamos explorar duas partes importantes desse processo: a atribuição em Python e os argumentos de função.
Compreendendo a Atribuição em Python
Em Python, quando você atribui um valor a uma variável, você está criando uma associação entre o nome da variável e o valor. Essa associação é chamada de referência. A variável é apenas um rótulo para o valor e você pode atualizar essa associação, criando uma nova referência para um novo valor.
No exemplo acima, as variáveis x
e y
são associadas ao objeto inteiro com valor 1. Ao atribuir y = x
, a variável y
recebe a mesma referência que a variável x
, apontando para o objeto inteiro de valor 1. No entanto, ao modificar o valor de x
para 2, uma nova referência é criada para o objeto inteiro com valor 2, enquanto a referência original de y
ainda aponta para o objeto com valor 1.
Explorando os Argumentos de Função
Quando você chama uma função em Python, os argumentos passados são tratados de maneira especial. Em vez de apenas copiar os valores, Python cria novas associações entre os nomes dos parâmetros e os argumentos passados. Isso significa que os parâmetros da função são referências para os argumentos, permitindo que a função acesse e modifique, por referência, os valores passados.
No exemplo acima, a função modify_argument
recebe uma referência para a variável value
e tenta modificar o seu valor para “modified”. No entanto, como o argumento arg
é uma nova referência para o mesmo objeto que value
, a modificação feita dentro da função não afeta a variável original value
.
Replicando a Passagem por Referência em Python
Embora Python não tenha suporte nativo para a passagem por referência como alguns outros idiomas, é possível replicar essa funcionalidade usando certas estruturas de dados mutáveis. Aqui estão algumas das melhores práticas para replicar a passagem por referência em Python:
Melhor Prática: Retornar e Atribuir Novamente
Uma forma comum de replicar a passagem por referência em Python é retornar um valor da função e atribuí-lo novamente à variável original.
No exemplo acima, a função modify_list
recebe uma lista my_list
, adiciona o número 4 a ela e retorna a lista modificada. Atribuir o retorno da função novamente à variável my_list
cria uma nova referência para a lista modificada.
Melhor Prática: Utilizar Atributos de Objeto
Outra abordagem é utilizar os atributos de objetos em Python para replicar a passagem por referência.
No exemplo acima, a classe DataContainer
possui um atributo data
que é modificado pela função modify_data
. Como a classe é mutável, qualquer modificação feita no atributo data
dentro da função afeta diretamente o objeto original.
Melhor Prática: Utilizar Dicionários e Listas
Dicionários e listas são tipos mutáveis em Python, o que significa que você pode utilizá-los para replicar a passagem por referência.
No exemplo acima, a função modify_dict
recebe um dicionário my_dict
e adiciona uma nova chave e valor a ele. Como o dicionário é mutável, a modificação é realizada diretamente no dicionário original.
Conclusão
Neste tutorial, você aprendeu sobre a passagem por referência em Python e como ela difere da passagem por valor. Exploramos várias construções de passagem por referência em Python, incluindo evitar objetos duplicados, retornar múltiplos valores, criar funções com múltiplos retornos condicionais e replicar a passagem por referência utilizando melhores práticas. Essas técnicas podem ser úteis para lidar com argumentos de função de forma mais eficiente e evitar surpresas indesejadas. Agora você está pronto para aplicar esses conceitos em suas próprias soluções Python.