16 de novembro de 2009

Várias atribuições na mesma linha

Em Python é possível atribuir um único conteúdo a mais de uma variável assim:
>>> x = y = 100
>>> x
100
>>> y
100

Esse é um jeito prático e funciona bem com strings, números e tuplas, mas esconde uma pegadinha com listas e dicionários. Veja um exemplo:
>>> a = b = ["abc", "def"]
>>> a
['abc', 'def']
>>> b
['abc', 'def']
>>>
>>> a.append("xyz")
>>> a
['abc', 'def', 'xyz']
>>>
>>> b  # atenção aqui!
['abc', 'def', 'xyz']
>>>

Agora, vejamos com um dicionário:
>>> a = b = {"cor": "branca", "fruta": "uva"}
>>> a
{'cor': 'branca', 'fruta': 'uva'}
>>> b
{'cor': 'branca', 'fruta': 'uva'}
>>> 
>>> a["comida"] = "arroz"
>>> a
{'cor': 'branca', 'fruta': 'uva', 'comida': 'arroz'}
>>> 
>>> b # atenção!
{'cor': 'branca', 'fruta': 'uva', 'comida': 'arroz'}
>>> 

Vimos que com listas e dicionários temos um "bug" aparente. Fique tranquilo, nós não encontramos um bug na linguagem!

Você vai entender melhor esse comportamento lendo Como as variáveis funcionam em Python e Como copiar listas e dicionários em Python.

A forma de evitar esse comportamento indesejado é não fazer múltiplas atribuições na mesma linha com tipos mutáveis (listas e dicionários):
>>> a = ["abc", "def"]
>>> b = ["abc", "def"]
>>> 
>>> a.append("xyz")
>>> a
['abc', 'def', 'xyz']
>>> 
>>> b
['abc', 'def']
>>> 

Aproveite e dê uma lida no post Pegadinha: parâmetro default que fala de um assunto parecido.

Eu sou Vinicius Assef, um programador do século passado que gosta de Python, pratica Lean Development e acredita em Deus. Você pode me contactar por email ou twitter.

3 comentários:

  1. # uma alternativa para atribuir varias listas

    a, b, c, d, e = ([] for _ in xrange(5))

    ResponderExcluir
  2. Esse tipo de pegadinha, creio eu, ( não tenho lá muitos conhecimentos em programação com python, afinal tenho apenas 16 anos, kk) é o fato dela fazer atribuição "diretamente" na memoria do objeto. Visto que os dois apontam para o mesmo endereço deve ser normal ambos os objetos armazerem o mesmo valor.

    E a alternativa citada assim é bem legal. xD

    Acho ser essa uma resposta.
    flw brother.

    ResponderExcluir
  3. Realmente, "a" e "b" possuem a mesma referencia e de fato uma operação realizada em "a" reflete em "b".

    ResponderExcluir

Marcadores