Estruturas de Dados

Prévio Próximo

Python Logo5. Estruturas de Dados

Este capítulo descreve algumas coisas que você já abordadou, porém com mais detalhes, e acrescenta algumas coisas novas também.

5.1. Mais em Listas

O tipo de dados list tem mais alguns métodos. Aqui estão todos os métodos de objetos list:

list.append (x)
Adicionar um item no fim da lista; equivalente a um [len (a):] = [x].

list.extend (L)
Aumentar a lista anexando todos os itens da lista fornecida; equivalente a um [len (a):] = L.
list.insert (i, x)
Inserir um item em uma determinada posição. O primeiro argumento é o índice do elemento antes de ser inserido, assim a.insert (0, x) insere na parte da frente da lista, e a.insert (len (a), x) é equivalente a a.append (x).
list.remove (x)
Retira o primeiro item da lista cujo valor é x. É um erro se não existe tal item.
list.pop ([i])
Remove o item da posição determinada na lista, e o retorna. Se nenhum índice for especificado, a.pop () remove e retorna o último item da lista. (Os colchetes ao redor do i na assinatura do método indicam que o parâmetro é opcional, não que você deve digitar colchetes nessa posição. Você vai ver esta notação frequentemente na Biblioteca de Referência Python.)
list.clear ()
Remove all items from the list. Equivalent to del a[:].
list.index (x)
Retorna o índice da lista do primeiro item cujo valor é x. É um erro se não existe tal item.
list.count (x)
Retorna o número de vezes x aparece na lista.
list.sort (CMP = None, key = None, reverter = False)
Organizar os itens da lista no lugar (os argumentos podem ser usados para personalização de classificação, ver sorted() para a sua explicação).
list.reverse ()
Inverte os elementos da lista, no local.
list.copy()
Return a shallow copy of the list. Equivalent to a[:].
Um exemplo que usa a maioria dos métodos de lista:
>>> a = [66.25, 333, 333, 1, 1234.5]
>>> print a.count(333), a.count(66.25), a.count('x')
2 1 0
>>> a.insert(2, -1)
>>> a.append(333)
>>> a
[66.25, 333, -1, 333, 1, 1234.5, 333]
>>> a.index(333)
1
>>> a.remove(333)
>>> a
[66.25, -1, 333, 1, 1234.5, 333]
>>> a.reverse()
>>> a
[333, 1234.5, 1, 333, -1, 66.25]
>>> a.sort()
>>> a
[-1, 1, 66.25, 333, 333, 1234.5]
>>> a.pop()
1234.5
>>> a
[-1, 1, 66.25, 333, 333]
Você deve ter notado que os métodos como insertremove ou sort só modificam a lista, não têm nenhum valor de retorno impresso – retornam o padrão None. [1] Trata-se de um princípio de design para todas as estruturas de dados mutáveis em Python.

5.1.1. usando Listas como Stacks

Os métodos list tornam muito fácil de usar uma lista como uma pilha (stack), onde o último elemento adicionado é o primeiro a ser recuperado (“last-in, first-out”). Para adicionar um item ao topo da pilha, use append(). Para recuperar um item do topo da pilha, use pop() sem um índice explícito. Por exemplo:
>>> stack = [3, 4, 5]
>>> stack.append(6)
>>> stack.append(7)
>>> stack
[3, 4, 5, 6, 7]
>>> stack.pop()
7
>>> stack
[3, 4, 5, 6]
>>> stack.pop()
6
>>> stack.pop()
5
>>> stack
[3, 4]

5.1.2. Usando Listas como Filas (Queues)

Existem três funções internas que são muito úteis quando utilizadas com listas: filter()map(), e reduce().

filter(function, sequence) retorna uma sequência consistindo dos itens da sequência para a qual function(item) é verdadeira. Se seqüência é um strunicode ou tuple, o resultado vai ser do mesmo tipo; caso contrário, é sempre uma list. Por exemplo, para calcular uma sequência de números divisíveis por 3 ou 5:

>>> def f(x): return x % 3 == 0 or x % 5 == 0
...
>>> filter(f, range(2, 25))
[3, 5, 6, 9, 10, 12, 15, 18, 20, 21, 24]
map(function, sequence) chama function(item) para cada um dos itens da seqüência e retorna uma lista de valores de retorno. Por exemplo, para calcular alguns cubos:
>>> def cube(x): return x*x*x
...
>>> map(cube, range(1, 11))
[1, 8, 27, 64, 125, 216, 343, 512, 729, 1000]
Mais do que uma sequência pode ser passada; a função deve, então, ter tantos argumentos como há sequências e é chamada com o item correspondente de cada sequência (ou None se alguma seqüência é mais curta do que a outra). Por exemplo:
>>> seq = range(8)
>>> def add(x, y): return x+y
...
>>> map(add, seq, seq)
[0, 2, 4, 6, 8, 10, 12, 14]
reduce(function, sequence) retorna um único valor calculado chamando a função binária function sobre os dois primeiros itens da seqüência, em seguida, no resultado e no próximo item, e assim por diante. Por exemplo, para calcular a soma dos números de 1 a 10:
>>> def add(x,y): return x+y
...
>>> reduce(add, range(1, 11))
55

Se há apenas um item na seqüência, o seu valor é retornado; se a sequência estiver vazia, uma exceção é gerada.

Um terceiro argumento pode ser passado para indicar o valor de início. Neste caso, o valor inicial é retornado para uma sequência vazia, e a função é aplicado em primeiro lugar ao valor de início e o primeiro item de sequência, em seguida, para o resultado e o ponto seguinte, e assim por diante. Por exemplo,

>>> def sum(seq):
...     def add(x,y): return x+y
...     return reduce(add, seq, 0)
...
>>> sum(range(1, 11))
55
>>> sum([])
0
Não utilize a definição de sum() deste exemplo: uma vez que soma números é uma necessidade tão comum, uma função interna sum(sequence) já está prevista, e funciona exatamente como este.

5.1.4. Compreenções de Lista

Compreensões de lista fornecem uma maneira concisa para criar listas. As aplicações mais comuns são para fazer novas listas onde cada elemento é o resultado de algumas operações aplicada a cada membro de uma outra seqüência ou iteração, ou para criar uma subsequência desses elementos que satisfazem uma determinada condição.

Por exemplo, suponha que queremos criar uma lista de quadrados, como:

>>> squares = []
>>> for x in range(10):
...     squares.append(x**2)
...
>>> squares
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
Podemos obter os mesmos resultados com:
squares = [x**2 for x in range(10)]

Isso também é equivalente a squares = map (lambda x: x ** 2, range (10)), mas é mais conciso e legível.

A compreensão de lista é composta por brackets que contêm uma expressão seguida de uma cláusula for, então zero ou mais cláusulas for ou if. O resultado será uma nova lista resultante da avaliação da expressão no contexto das cláusulas for e if que seguem. Por exemplo, este listcomp combina os elementos de duas listas, se eles não forem iguais:

>>> [(x, y) for x in [1,2,3] for y in [3,1,4] if x != y]
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]
E é equivalente à:
>>> combs = []
>>> for x in [1,2,3]:
...     for y in [3,1,4]:
...         if x != y:
...             combs.append((x, y))
...
>>> combs
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]
Note como a ordem das declarações for e if é a mesma em ambos os trechos.
Se a expressão for um tuple (por exemplo, a (x, y) no exemplo anterior), deve estar entre parênteses.
>>> vec = [-4, -2, 0, 2, 4]
>>> # create a new list with the values doubled
>>> [x*2 for x in vec]
[-8, -4, 0, 4, 8]
>>> # filter the list to exclude negative numbers
>>> [x for x in vec if x >= 0]
[0, 2, 4]
>>> # apply a function to all the elements
>>> [abs(x) for x in vec]
[4, 2, 0, 2, 4]
>>> # call a method on each element
>>> freshfruit = ['  banana', '  loganberry ', 'passion fruit  ']
>>> [weapon.strip() for weapon in freshfruit]
['banana', 'loganberry', 'passion fruit']
>>> # create a list of 2-tuples like (number, square)
>>> [(x, x**2) for x in range(6)]
[(0, 0), (1, 1), (2, 4), (3, 9), (4, 16), (5, 25)]
>>> # the tuple must be parenthesized, otherwise an error is raised
>>> [x, x**2 for x in range(6)]
  File "<stdin>", line 1
    [x, x**2 for x in range(6)]
               ^
SyntaxError: invalid syntax
>>> # flatten a list using a listcomp with two 'for'
>>> vec = [[1,2,3], [4,5,6], [7,8,9]]
>>> [num for elem in vec for num in elem]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
Compreensões de lista pode conter expressões complexas e funções aninhadas:
>>> from math import pi
>>> [str(round(pi, i)) for i in range(1, 6)]
['3.1', '3.14', '3.142', '3.1416', '3.14159']

5.1.4.1. Compreenções de Lista Aninhadas

A expressão inicial em uma compreensão da lista pode ser qualquer expressão arbitrária, incluindo uma outra compreensão da lista.

Considere o exemplo seguinte de uma matriz 3×4 implementada como uma lista de três listas de comprimento 4:

>>> matrix = [
...     [1, 2, 3, 4],
...     [5, 6, 7, 8],
...     [9, 10, 11, 12],
... ]
A seguinte compreensão de lista irá transpor linhas e colunas:
>>> [[row[i] for row in matrix] for i in range(4)]
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
Como vimos na seção anterior, a listcomp aninhada é avaliada no contexto do for que o segue, de modo que este exemplo é equivalente a:
>>> transposed = []
>>> for i in range(4):
...     transposed.append([row[i] for row in matrix])
...
>>> transposed
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
que, por sua vez, é o mesmo que:
>>> transposed = []
>>> for i in range(4):
...     # the following 3 lines implement the nested listcomp
...     transposed_row = []
...     for row in matrix:
...         transposed_row.append(row[i])
...     transposed.append(transposed_row)
...
>>> transposed
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
No mundo real, você deve preferir funções internas para demonstrações de fluxo complexos. A função zip() iria fazer um grande trabalho para este caso de uso:
>>> zip(*matrix)
[(1, 5, 9), (2, 6, 10), (3, 7, 11), (4, 8, 12)]
Veja Desempacotando Listas de Argumentos para obter detalhes sobre o asterisco nesta linha.

.2. A instrução del

Existe uma maneira de remover um item de uma lista dado seu índice em vez do seu valor: a instrução del. Esta difere do método pop(), que retorna um valor. A instrução del também pode ser usada para remover as fatias de uma lista ou limpar toda a lista (que fizemos anteriormente por cessão de uma lista vazia para a fatia). Por exemplo:
>>> a = [-1, 1, 66.25, 333, 333, 1234.5]
>>> del a[0]
>>> a
[1, 66.25, 333, 333, 1234.5]
>>> del a[2:4]
>>> a
[1, 66.25, 1234.5]
>>> del a[:]
>>> a
[]
del pode ser usado tambem para deletar variáveis inteiramente.
>>> del a
Fazendo referência ao nome a daqui por diante será um erro (pelo menos até que outro valor seja atribuído a ela). Vamos encontrar outros usos para del mais tarde.

5.3. Tuples e Sequências

Nós vimos que listas e strings possuem muitas propriedades comuns, tais como operações de indexação e de fatiação (slice). Esses são dois exemplos de tipos de dados de seqüência (consulte Tipos de Seqüência – str, unicode, lista, tuple, bytearray, buffer, xrange). Desde que Python é uma linguagem em evolução, podem ser adicionados outros tipos de dados de seqüência. Há também um outro tipo de sequência: a tuple.

Uma tuple consiste de um número de valores separados por vírgulas, por exemplo:

>>> t = 12345, 54321, 'hello!'
>>> t[0]
12345
>>> t
(12345, 54321, 'hello!')
>>> # Tuples may be nested:
... u = t, (1, 2, 3, 4, 5)
>>> u((12345, 54321, 'hello!'), (1, 2, 3, 4, 5))
>>> # Tuples are immutable:
... t[0] = 88888
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
>>> # but they can contain mutable objects:
... v = ([1, 2, 3], [3, 2, 1])
>>> v
([1, 2, 3], [3, 2, 1])

Como você vê, na saída tuples são sempre colocadas entre parênteses, para que tuples aninhadas sejam interpretadas corretamente; elas podem ser introduzidas com ou sem parênteses, parênteses embora muitas vezes são necessários qualquer forma (se a tuple faz parte de uma expressão maior). Não é possível atribuir aos itens individuais de uma tuple, no entanto, é possível criar tuples contendo objetos mutáveis, como listas.

Embora tuples podem parecer semelhantes a listas, elas são muitas vezes utilizadas em diferentes situações e para diferentes fins. Tuples são imutáveis, e geralmente contêm uma sequência heterogênea de elementos que são acessados ​​através de descompactação (veja mais adiante nesta seção) ou indexação (ou mesmo por atributo, no caso de namedtuples). As listas são mutáveis, e seus elementos são geralmente homogêneo e são acessados ​​por iteração sobre a lista.

Um problema especial é a construção de tuplas contendo 0 ou 1 itens: a sintaxe tem alguns truques para acomodá-las. Tuples vazias são construídas por um par de parênteses vazio; uma tupla com um item é construída seguindo um valor com uma vírgula (, não é suficiente para incluir um único valor em parênteses). Feio, mas eficaz. Por exemplo:

>>> empty = ()
>>> singleton = 'hello',    # <-- note trailing comma
>>> len(empty)
0
>>> len(singleton)
1
>>> singleton
('hello',)
A declaração t = 12345, 54321, ‘hello!’ é um exemplo de embalagem tuple: os valores 12345, 54321 e ‘Olá’ são embalados juntos em uma tuple. A operação inversa também é possível:
>>> x, y, z = t
Isso é chamado, apropriadamente, seqüência de desembalar e funciona para qualquer sequência no lado da mão direita. Sequência de desempacotamento requer a lista de variáveis do lado esquerdo para ter o mesmo número de elementos como o comprimento da sequência. Note-se que a atribuição múltipla é realmente apenas uma combinação de embalagem tuple e sequência de desembalar.

5.4. Sets

Python também inclui um tipo de dados para conjuntos (set). Um conjunto é uma coleção desordenada sem elementos duplicados. Usos básicos incluem testes de adesão e eliminar entradas duplicadas. Objetos set também suportam operações matemáticas como união, intersecção, diferença e diferença simétrica.

Chaves ou a função set() pode ser usada para criar sets. Nota: para criar um set vazio que você tem que usar set(), não {}; o último cria um dicionário vazio, uma estrutura de dados que vamos discutir na próxima seção.

Aqui está uma breve demonstração:

>>> basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
>>> fruit = set(basket)               # create a set without duplicates
>>> fruit
set(['orange', 'pear', 'apple', 'banana'])
>>> 'orange' in fruit                 # fast membership testing
True
>>> 'crabgrass' in fruit
False

>>> # Demonstrate set operations on unique letters from two words
...
>>> a = set('abracadabra')
>>> b = set('alacazam')
>>> a                                  # unique letters in a
set(['a', 'r', 'b', 'c', 'd'])
>>> a - b                              # letters in a but not in b
set(['r', 'd', 'b'])
>>> a | b                              # letters in either a or b
set(['a', 'c', 'r', 'd', 'b', 'm', 'z', 'l'])
>>> a & b                              # letters in both a and b
set(['a', 'c'])
>>> a ^ b                              # letters in a or b but not both
set(['r', 'd', 'b', 'm', 'z', 'l'])
Da mesma forma que para a lista compreensões, compreensões set também são suportados:
>>> a = {x for x in 'abracadabra' if x not in 'abc'}
>>> a
set(['r', 'd'])

5.5. Dicionários

Outro tipo de dados útil embutido em Python é o dicionário (dictionary – ver tipos de mapeamento – dict). Dicionários as vezes são encontrados em outras linguagens como “memórias associativas” ou “matrizes de associação”. Diferentemente de sequências que são indexadas por uma série de números, os dicionários são indexados por chaves, que podem ser qualquer tipo imutável; strings e números podem ser sempre chaves. Tuples podem ser usadas como chaves se contiverem apenas strings, números ou tuples; Se a tuple contiver qualquer valor mutável, direta ou indiretamente, ela não pode ser usada como uma chave. Você não pode usar listas como chaves, uma vez que as listas podem ser modificadas no local usando as atribuições do índice, as atribuições fatia, ou métodos como append () e extend().
É melhor pensar em um dicionário como um conjunto desordenado de chave: pares de valores (value-pairs), com a exigência de que as chaves sejam únicas (dentro de um dicionário). Um par de curly-braces cria um dicionário vazio: {}. Colocando uma lista de chaves value-pairs separadas por vírgula dentro dos curly-braces acrescenta a inicial key-value-pairs ao dicionário; esta é também a forma como dicionários são escritos na saída.
As principais operações em um dicionário são rmazenar um valor com alguma chave e extrair o valor dado a chave. Também é possível excluir um par de key-value com del. Se você armazenar usando uma chave que já está em uso, o valor antigo associado a essa tecla é esquecido. Gera um erro tentar extrair um valor usando uma chave inexistente.
O método keys() de um dicionário retorna a lista de todas as chaves utilizadas no dicionário, de forma arbitrária (se você quiser ordená-las basta aplicar a função de sorted() no método). Para verificar se uma única chave está no dicionário, use a palavra-chave in.
Aqui está  um pequeno exemplo usando um dicionário:
>>> tel = {'jack': 4098, 'sape': 4139}
>>> tel['guido'] = 4127
>>> tel
{'sape': 4139, 'guido': 4127, 'jack': 4098}
>>> tel['jack']
4098
>>> del tel['sape']
>>> tel['irv'] = 4127
>>> tel
{'guido': 4127, 'irv': 4127, 'jack': 4098}
>>> tel.keys()
['guido', 'irv', 'jack']
>>> 'guido' in tel
True
O construtor dict() constrói dicionários diretamente a partir de seqüências de pares de key-value:
>>> dict([('sape', 4139), ('guido', 4127), ('jack', 4098)])
{'sape': 4139, 'jack': 4098, 'guido': 4127}
Além disso, compreensões de dicionários podem ser usados para criar dicionários a partir de expressões arbitrárias de key-value:
>>> {x: x**2 for x in (2, 4, 6)}
{2: 4, 4: 16, 6: 36}
Quando as chaves são strings simples, às vezes é mais fácil especificar pares usando argumentos:
>>> dict(sape=4139, guido=4127, jack=4098)
{'sape': 4139, 'jack': 4098, 'guido': 4127}

5.6. Técnicas de Loop

Quando fizer loop através de uma seqüência, o índice de posição e valor correspondente pode ser recuperada ao mesmo tempo usando a função enumerate().
>>> for i, v in enumerate(['tic', 'tac', 'toe']):
...     print i, v
...
0 tic
1 tac
2 toe
Para fazer loop sobre duas ou mais sequências, ao mesmo tempo, as entradas podem ser emparelhadas com a função zip().
>>> questions = ['name', 'quest', 'favorite color']
>>> answers = ['lancelot', 'the holy grail', 'blue']
>>> for q, a in zip(questions, answers):
...     print 'What is your {0}?  It is {1}.'.format(q, a)
...
What is your name?  It is lancelot.
What is your quest?  It is the holy grail.
What is your favorite color?  It is blue.
Para loop sobre uma sequência em sentido inverso, primeiro especificar a seqüência para a frente e, em seguida, chamar a função reverse().
>>> for i in reversed(xrange(1,10,2)):
...     print i
...
9
7
5
3
1
Para loop sobre uma sequência na ordem de classificação, use a função sorted(), que retorna uma nova lista ordenada, deixando a fonte inalterada.
>>> basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
>>> for f in sorted(set(basket)):
...     print f
...
apple
banana
orange
pear
Quando um loop através de dicionários, o valor da chave e correspondente pode ser recuperada ao mesmo tempo usando o método iteritems().
>>> knights = {'gallahad': 'the pure', 'robin': 'the brave'}
>>> for k, v in knights.iteritems():
...     print k, v
...
gallahad the pure
robin the brave
Para alterar a seqüência sobre o que você está interagindo enquanto no interior do loop (por exemplo, para duplicar certos itens), é recomendável que você primeiro faça uma cópia. Fazendo loop sobre uma sequência não faz uma cópia implicitamente. A notação slice faz isto especialmente conveniente:
>>> words = ['cat', 'window', 'defenestrate']
>>> for w in words[:]:  # Loop over a slice copy of the entire list.
...     if len(w) > 6:
...         words.insert(0, w)
...
>>> words
['defenestrate', 'cat', 'window', 'defenestrate']

5.7. Mais sobre Condições

As condições usadas em declarações while e if podem conter todos os operadores, e não apenas comparações.

Os operadores de comparação in e not in checa se um valor ocorre (não ocorre) em uma seqüência. Os operadores is e is not comparam se dois objetos são realmente o mesmo objeto; o que só importa para objetos mutáveis, como listas. Todos os operadores de comparação tem a mesma prioridade, que é menor do que a de todos os operadores numéricos.

Comparações podem ser encadeadas. Por exemplo, a <b == c testa se a é menor que b e por outro lado b igual a c.

As comparações podem ser combinadas usando os operadores booleanos AND e OR, e o resultado de uma comparação (ou de qualquer outra expressão booleana) pode ser negativado com not. Estes têm prioridades mais baixas do que os operadores de comparação; entre eles, não tem a prioridade mais alta ou a mais baixa e, de modo que A and not B or C é equivalente a (A and (not B)) or C. Como sempre, parênteses podem ser usados para expressar a composição desejada.

Os operadores booleanos AND e OR são os chamados operadores de curto-circuito: os seus argumentos são avaliados da esquerda para a direita, e avaliação pára assim que o resultado é determinado. Por exemplo, se A e C são verdadeiras, mas B é falso, A e B e C não avaliar a expressão C. Quando usado como um valor geral e não como um booleano, o valor de retorno de um operador de curto-circuito é a última argumento avaliada.

É possível atribuir o resultado de uma comparação ou outra expressão booleana para uma variável. Por exemplo,

>>> string1, string2, string3 = '', 'Trondheim', 'Hammer Dance'
>>> non_null = string1 or string2 or string3
>>> non_null
'Trondheim'
Note-se que em Python, ao contrário de C, atribuição não pode ocorrer dentro de expressões. Programadores C podem resmungar, mas isso evita toda uma classe de problemas frequentemente encontrados em programas C: digitar = numa expressão quando == foi pretendido.

5.8. Comparando Sequências com Outros Tipos

Os objectos de Sequência podem ser comparados com outros objectos do mesmo tipo de sequência. A comparação usa ordenação lexicográfica: primeiro, os dois primeiros itens são comparados, e se diferirem isto determina o resultado da comparação; se forem iguais, os próximos dois itens são comparados, e assim por diante, até que se esgota sequência. Se dois itens a serem comparados são eles próprios sequências do mesmo tipo, a comparação léxicografica é realizada de forma recursiva. Se todos os itens de duas sequências se compararem iguais, as sequências são consideradas iguais. Se uma sequência é uma sub-sequência inicial da outra, a sequência mais curta é a menor. Ordenação lexicográfica para strings usa a ordenação ASCII para caracteres individuais. Alguns exemplos de comparações entre sequências do mesmo tipo:
(1, 2, 3)              < (1, 2, 4)
[1, 2, 3]              < [1, 2, 4]
'ABC' < 'C' < 'Pascal' < 'Python'
(1, 2, 3, 4)           < (1, 2, 4)
(1, 2)                 < (1, 2, -1)
(1, 2, 3)             == (1.0, 2.0, 3.0)
(1, 2, ('aa', 'ab'))   < (1, 2, ('abc', 'a'), 4)
Note-se que comparando objetos de diferentes tipos é legal. O resultado é determinista, mas arbitrário: os tipos são ordenados pelos seus nomes. Assim, uma lista é sempre menor do que uma string, uma string é sempre menor do que uma tuple, etc. [1] tipos numéricos mistos são comparados de acordo com o seu valor numérico, então 0 é igual a 0.0, etc.
Footnotes
[1] As regras para a comparação de objetos de diferentes tipos não devem ser invocadas; elas podem mudar em uma versão futura do idioma.
Prévio Próximo