HomePage RecentChanges

Lesson09

Listas

As listas em Python são idênticas aos tuplos, mas com uma diferença fundamental: as listas são mutáveis, i.e., os seus elementos podem ser modificados, adicionados ou removidos.

A definição de listas é também semelhante à definição de tuplos, em que se utilizam [] em vez de (). Em notação BNF:

<lista> ::= [] | [<elementos>]

<elementos> ::= <elemento> | <elemento>, <elementos>

<elemento> ::= <expressão> | <tuplo> | <lista> | <dicionário>

Notar que, dada a inexistência de ambiguidade em relação ao uso de [], contrariamente ao que acontece com o uso de () como vimos no caso da representação de tuplos, as listas com um elemento não contêm , no final.

Exemplos, incluindo o uso de algumas funções pré-definidas:

>>> lst1 = [2, 3, 5, 7]
>>> lst2 = [0, 1, 1, 2, 3, 5, 8]
>>> lst1 + lst2
[2, 3, 5, 7, 0, 1, 1, 2, 3, 5, 8]
>>> lst1*5
[2, 3, 5, 7, 2, 3, 5, 7, 2, 3, 5, 7, 2, 3, 5, 7, 2, 3, 5, 7]
>>> 3*lst1
[2, 3, 5, 7, 2, 3, 5, 7, 2, 3, 5, 7]
>>> lst2[2:5]
[1, 2, 3]
>>> del(lst2[2:5])
>>> lst2
[0, 1, 5, 8]
>>> 8 in lst2
True
>>> 8 in lst1
False
>>> 8 not in lst1
True
>>> len(lst1)
4
>>> list((8,9,4))
[8, 9, 4]
>>> list('Fundamentos')
['F', 'u', 'n', 'd', 'a', 'm', 'e', 'n', 't', 'o', 's']
>>> lst1[1] = 'FP'
>>> lst1
[2, 'FP', 5, 7]
>>>

Associação de nomes e listas:

>>> lst1 = [2, 3, 5, 7]
>>> lst2 = lst1
>>> lst1[2] = 6
>>> lst1
[2, 3, 6, 7]
>>> lst2
[2, 3, 6, 7]
>>> lst2[1] = 4
>>> lst1
[2, 4, 6, 7]
>>>

É importante lembrar que em Python todos as entidades são objectos, o que será discutido mais em detalhe adiante, e que a atribuição não é mais do que a associação de um nome a um objecto. Neste exemplo, ambos os nomes são associados à mesma lista e, portanto, ambos observam a mesma lista e as mesmas alterações sobre a mesma. Não esquecer que as listas são mutáveis.

Exercício: Represente graficamente o ambiente e as associações no exemplo anterior.

Mais detalhes a respeito das operações possíveis sobre listas na documentação de Python.

Passagem por valor e por referência

É comum falarmos em passagem de argumentos por valor e por referência quando estudamos linguagens de programação. Em Python todas as entidades são objectos e esses objectos são passados como argumentos por referência. No entanto as referências são passadas por valor. Numa primeira análise pode parecer confuso, mas basta pensar na passagem de parâmetros como associações entre nomes e objectos/valores.

Neste contexto uma referência denota a localização na memória em que se encontra um dado valor/objecto. A associação de um nome a um valor pode ser visto aqui como a atribuição da referência do valor/objecto ao nome.

Na passagem de argumentos por valor, os valores associados aos argumentos formais de uma função são distintos dos valores associados aos parâmetros concretos utilizados na invocação da função. Ou seja, as referência ou localizações na memória são distintas.

Na passagem de argumentos por referência dos objectos, os valores associados aos argumentos formais de uma função são os mesmos que os valores associados aos parâmetros concretos na invocação da função. Ou seja, as referências ou localizações na memória são as mesmas. Isto implica que alterações aos valores/objectos realizadas pela função são observáveis fora do ambiente da mesma. No entanto essas alterações apenas são possíveis em Python sobre objectos mutáveis, como as listas. Se os objectos/valores forem imutáveis, como os tuplos ou as cadeias de caracteres ou os números, podemos ficar com a falsa impressão de que a passagem de argumentos é por valor.

Antes de passarmos a alguns exemplos nota-se que distingue-se aqui passagem por referência dos objectos de passagem por referência no sentido em que, em geral, a passagem por referência permite muitas vezes alterar numa função o valor da referência em ambientes externos à função, o que em Python corresponderia a uma função alterar a associação entre nomes e objectos fora do ambiente da mesma. Como vimos em aulas anteriores, este não é o caso em Python.

>>> def addtoall(t, x):
...     for l in t:
...         l.append(x)
...     t = ()
... 
>>> t = ([], [])
>>> addtoall(t, 2)
>>> addtoall(t, 3)
>>> addtoall(t, 5)
>>> t
([2, 3, 5], [2, 3, 5])
>>>

Neste exemplo pode observar-se que o argumento t é passado por referência para o valor/objecto associado, caso contrário as alterações sobre as listas não seriam observáveis fora do ambiente da função. No entanto a referência em si foi passada por valor uma vez que a atribuição no final da função não tem efeito no ambiente global, facto que já tínhamos visto quando analisámos os ambientes e a associação de nomes.