{"id":18357758,"url":"https://github.com/andreadcsousa/alura_listas-tuplas-collections_python","last_synced_at":"2025-04-10T02:32:47.027Z","repository":{"id":168043325,"uuid":"599378515","full_name":"andreadcsousa/alura_listas-tuplas-collections_python","owner":"andreadcsousa","description":"Este projeto faz parte do plano de estudos elaborado pela Alura para o programa de formação Desenvolve (3ª edição), trilha de dados, em parceria com a Boticário.","archived":false,"fork":false,"pushed_at":"2023-02-11T03:26:31.000Z","size":137,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-15T17:52:13.229Z","etag":null,"topics":["alura","aprendendo","boticario","collections-python","dados","desenvolve-2023","desenvolve-3-edicao","python"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/andreadcsousa.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-02-09T02:18:35.000Z","updated_at":"2023-02-09T02:20:46.000Z","dependencies_parsed_at":null,"dependency_job_id":"a53bedc2-bc05-42bd-96c9-ef445838be76","html_url":"https://github.com/andreadcsousa/alura_listas-tuplas-collections_python","commit_stats":null,"previous_names":["andreadcsousa/alura_listas-tuplas-collections_python"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andreadcsousa%2Falura_listas-tuplas-collections_python","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andreadcsousa%2Falura_listas-tuplas-collections_python/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andreadcsousa%2Falura_listas-tuplas-collections_python/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andreadcsousa%2Falura_listas-tuplas-collections_python/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/andreadcsousa","download_url":"https://codeload.github.com/andreadcsousa/alura_listas-tuplas-collections_python/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248144294,"owners_count":21054904,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["alura","aprendendo","boticario","collections-python","dados","desenvolve-2023","desenvolve-3-edicao","python"],"created_at":"2024-11-05T22:15:21.289Z","updated_at":"2025-04-10T02:32:47.020Z","avatar_url":"https://github.com/andreadcsousa.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Python Collections parte 1: listas e tuplas\n\nAbordagem de lista, tupla, existência das arrays como tipos dentro do Python e das arrays do numpy.\n\n1. [Listas e operações](#1-listas-e-operações)\n2. [Tuplas](#2-tuplas)\n3. [Polimorfismo e arrays](#3-polimorfismo-e-arrays)\n4. [Igualdade](#4-igualdade)\n5. [Outros builtins](#5-outros-builtins)\n6. [Ordem natural](#6-ordem-natural)\n7. [Ordenação customizada](#7-ordenação-customizada)\n8. [Ordenação total](#8-ordenação-total)\n\nSaiba mais sobre o curso [aqui](https://cursos.alura.com.br/course/python-collections-listas-e-tuplas) ou acompanhe minhas anotações abaixo. ⬇️\n\n## 1. Listas e operações\n\n### **Introdução as coleções e lista**\n\nPara entender melhor os elementos de listas, utiliza-se métodos de inserção e remoção de itens, numa lista de objetos. A função `.append()` adiciona um item ao final da lista, mesmo que o item já exista na lista. Já a função `.remove()` apaga a primeira inserção de um item da lista, por exemplo:\n\n```py\nidades = [39, 30, 27]\n\nidades.append(18)       # retorna [39, 30, 27, 18]\n\ntype(idades)            # retorna list\nlen(idades)             # retorna 4\n\nidades[0]               # retorna 39\n\nidades.append(15)       # retorna [39, 30, 27, 18, 15]\n\nfor idade in idades:\n    print(idade)        # retorna 39 30 27 18 15\n\nidades.remove(30)       # retorna [39, 27, 18, 15]\n\nidades.append(27)       # retorna [39, 27, 18, 15, 27]\nidades.remove(27)       # retorna [39, 18, 15, 27]\n\nidades.clear()          # remove todos os itens da lista\n```\n\n### **Mais operações em lista e list comprehension**\n\nPara realizar uma verificação no itens da lista, pode-se perguntar isso utilizando o `in` ou pode-se utilizar o `if` para verificar e já fazer uma modificação na lista. Para inserir um item em um ponto específico da lista, utiliza-se a função `insert(posição, valor)`, diferente do append que só recebe um argumento, por exemplo:\n\n```py\nidades = [39, 18, 15, 27]\n\n28 in idades            # retorna False\n15 in idades            # retorna True\n\nif 15 in idades:        # retorna [39, 18, 27]\n    idades.remove(15)\n\nif 28 in idades:        # retorna [39, 18, 27], pois 28 não existe na lista\n    idades.remove(28)\n\nidades.append(19)       # retorna [39, 18, 27, 19]\nidades.insert(0, 20)    # retorna [20, 39, 18, 27, 19]\n\nidades = [20, 39, 18]\n\nidades.append(27, 19)   # retorna erro\nidades.append([27, 19]) # retorna [20, 39, 18, [27, 19]]\n\nfor elemento in idades:\n    print(\"Recebi o elemento\", elemento)\n\n# Recebi o elemento 20\n# Recebi o elemento 39\n# Recebi o elemento 18\n# Recebi o elemento [27, 19]\n```\n\nPara resolver a questão da inserção de itens na lista, sem que eles retornem outra lista dentro da anterior, usa-se a função `.extend()`. No caso de querer criar uma lista a partir de outra, cria-se uma lista vazia, depois utiliza-se a função `.append()` para adicionar mais itens, por exemplo:\n\n```py\nidades.extend([27, 19])       # retorna [20, 39, 18, 27, 19]\n\nidades = [20, 39, 18, 27, 19]\nidades_no_ano_que_vem = []\n\nfor idade in idades:          # retorna [21, 40, 19, 28, 20] na lista \"idades_no_ano_que_vem\"\n    idades_no_ano_que_vem.append(idade + 1)\nidades_no_ano_que_vem\n\n# utilizando list comprehension = função + iteração + condição\nidades = [20, 39, 18, 27, 19]\nidades_no_ano_que_vem = []\n\n[(idade + 1) for idade in idades]           # retorna [21, 40, 19, 28, 20]\n[(idade) for idade in idades if idade \u003e 21] # retorna [39, 27] pois filtra números menores que 21\n\n# definindo uma função com list comprehension, aplicando filtros e transformações\ndef proximo_ano(idade):\n    return idade + 1\n\n[proximo_ano(idade) for idade in idades if idade \u003e 21]\n```\n\n### **Problemas da mutabilidade da lista**\n\n\u003e Python tem objetos mutáveis e imutáveis. Os mutáveis contêm estado interno, como atributos, que podem ser alterados durante sua existência. Já os imutáveis não podem ser alterados e seu estado pode ser definido somente em sua inicialização.\n\nSão mutáveis:\n\n- `list` estrutura de dados que armazena dados em sequência, com índice\n- `dict` coleção de itens desordenados, com identificador\n- `set` coleção de itens desordenados, não duplicados\n\nSão imutáveis:\n\n- `tuple` estrutura de dados que armazena dados em sequência, com índice\n- `str` cadeia de caracteres que representam textos\n- `int` conjunto de números inteiros (positivos, negativos, zero)\n- `float` conjunto de números decimais (possuem partes fracionadas)\n\n```py\ndef processa_visualizacao(lista):\n    print(len(lista))\n\nidades = [16, 21, 29, 56, 43]\nprocessa_visualizacao(idades)   # retorna 5 como tamanho da lista e [16, 21, 29, 56, 43] como valores\n\n\ndef processa_visualizacao(lista):\n    print(len(lista))\n    lista.append(13)\n\nidades = [16, 21, 29, 56, 43]\nprocessa_visualizacao(idades)   # retorna 5 como tamanho da lista e [16, 21, 29, 56, 43, 13] como valores\n\n\n# trabalhando com a mutabilidade das listas\ndef processa_visualizacao(lista = []):      # lista vazia\n    print(len(lista))\n    lista.append(13)\nprocessa_visualizacao()     # retorna 0\nprocessa_visualizacao()     # retorna 1\nprocessa_visualizacao()     # retorna 2\nprocessa_visualizacao()     # retorna 3\n\ndef processa_visualizacao(lista = []):\n    print(len(lista))\n    print(lista)            # imprimindo a lista\n    lista.append(13)\nprocessa_visualizacao()     # retorna 0 []\nprocessa_visualizacao()     # retorna 1 [13]\nprocessa_visualizacao()     # retorna 2 [13, 13]\nprocessa_visualizacao()     # retorna 3 [13, 13, 13]\n\ndef processa_visualizacao(lista = list()):  # lista de objetos vazia\n    print(len(lista))\n    print(lista)\n    lista.append(13)\nprocessa_visualizacao()     # retorna 0 []\nprocessa_visualizacao()     # retorna 1 [13]\nprocessa_visualizacao()     # retorna 2 [13, 13]\nprocessa_visualizacao()     # retorna 3 [13, 13, 13]\n\ndef processa_visualizacao(lista = None):    # nada, falta de valor\n    if lista == None:\n        lista = list()      # se a lista não tem nada, cria uma nova lista\n    print(len(lista))\n    print(lista)\n    lista.append(13)\nprocessa_visualizacao()     # retorna 0 []\nprocessa_visualizacao()     # retorna 0 []\nprocessa_visualizacao()     # retorna 0 []\nprocessa_visualizacao()     # retorna 0 []\n```\n\n## 2. Tuplas\n\n### **Listas com objetos de classes nossas**\n\nAo criar listas com objetos que são instanciados por classes, é necessário atentar para a referência que for criada para cada objeto da lista. Um objeto pode ser referenciado várias vezes, mesmo que seja instanciado apenas uma vez na classe. Como exemplo, têm-se 2 contas distintas, mas uma delas é referenciada em duplicidade, veja:\n\n```py\n# criação da classe \"ContaCorrente\"\nclass ContaCorrente:\n\n    def __init__(self, codigo):\n        self.codigo = codigo\n        self.saldo = 0\n\n    def deposita(self, valor):\n        self.saldo += valor\n\n    def __str__(self):\n        return \"[\u003e\u003e Código {} Saldo {} \u003c\u003c]\".format(self.codigo, self.saldo)\n\n# criação das contas\nconta_andrea = ContaCorrente(15)\nconta_andrea.deposita(500)\nprint(conta_andrea)                 # retorna [\u003e\u003e Código 15 Saldo 500 \u003c\u003c]\n\nconta_eloisa = ContaCorrente(18)\nconta_eloisa.deposita(1000)\nprint(conta_eloisa)                 # retorna [\u003e\u003e Código 18 Saldo 1000 \u003c\u003c]\n\n# análise dos objetos criados\ncontas = [conta_andrea, conta_eloisa]\nfor conta in contas:\n    print(conta)                 # retorna [\u003e\u003e Código 15 Saldo 500 \u003c\u003c] e [\u003e\u003e Código 18 Saldo 1000 \u003c\u003c]\n\n# referência das contas\ncontas = [conta_andrea, conta_eloisa, conta_andrea]\n#           posição 0     posição 1     posição 2\nprint(contas[0])\nprint(contas[2])            # todos retornam [\u003e\u003e Código 15 Saldo 500 \u003c\u003c]\nprint(contas[conta_andrea]) # pois é a mesma conta, o mesmo objeto referenciado várias vezes\n```\n\n### **Tuplas, objetos e anemia**\n\nAo definir que a posição da lista seja o número da agência, todas as contas passam a ter o código da agência como sua posição da lista. Não sendo mais possível chamar as contas pela posição em que aparecem na lista e, sim, pela sua referência base, ou seja, o nome da conta.\n\n```py\ndef deposito_em_conta(contas):\n    for conta in contas:\n        conta.deposita(100)\n\ncontas = [conta_andrea, conta_eloisa]\nprint(contas[0], contas[1])\n\ndeposito_em_conta(contas)\nprint(contas[0], contas[1])\n\ncontas.insert(0, 76)\nprint(contas[0], contas[1], contas[2])  # imprime o código da agência e os dados das contas\n\ndeposito_em_conta(contas)\nprint(contas[0], contas[1], contas[2])  # retorna erro, pois o 76 não faz referência a uma conta\n```\n\nQuando não se quer que uma lista seja mutável, o correto é usar a `tupla`. Representada entre parênteses, pode conter um ou mais valores e não aceita inserção de dados após a criação da lista. Contudo, pode-se criar uma função com uma `variação funciona`l, separando o comportamento dos dados.\n\n```py\nandrea = ('Andrea', 35, 1987)\nneuza = ('Neuza', 63, 1959)\n\nandrea.append(978264)   # retorna erro\n\n\nconta_andrea = (15, 100)\nconta_andrea[1]\n\ndef deposita(conta):\n    novo_saldo = conta[1] + 100\n    codigo = conta[0]\n    return (codigo, novo_saldo)\n\ndeposita(conta_andrea)                  # retorna 15, 200 / nova tupla\nconta_andrea                            # retorna 15, 100 / variável original\n\nconta_andrea = deposita(conta_andrea)   # retorna 15, 200 / reatribuição da variável original\nconta_andrea\n```\n\n\u003e Listas nos levam a variação orientada a objetos e tuplas nos levam a variação funcional.\n\n- Se a posição indica alguma coisa, provavelmente tem um tamanho fixo, então provavelmente é uma tupla.\n- Se a posição não tem tipo definido, específico, sendo tudo do mesmo tipo, então provavelmente é uma lista.\n\n### **Tupla de objetos e lista de tuplas**\n\nÉ possível criar listas de tuplas. Tais listas irão armazenar informações que foram passadas anteriormente em tuplas com dados individuais dos \"usuários\". A tupla não deixa adicionar ou remover elementos dela, mas é possível adicionar e remover \"referências de referenciados\", ou seja, alterar os objetos da tupla.\n\n```py\nusuarios = [andrea, neuza]\nusuarios\n# retorna [('Andrea', 35, 1987) e ('Neuza', 63, 1959)]\n\nusuarios.append(('Eloisa', 9, 2013))\nusuarios\n# retorna [('Andrea', 35, 1987) ('Neuza', 63, 1959) e ('Eloisa', 9, 2013)]\n\nusuarios[0]                     # retorna o usuário na posição 0 - [('Andrea', 35, 1987)]\nusuarios[0][0] = 'Andrea Sousa' # retorna erro, pois não é possível modificar os valores de uma tupla\n\n# identificando contas e depósitos\nconta_andrea = ContaCorrente(15)\nconta_andrea.deposita(500)\n\nconta_eloisa = ContaCorrente(18)\nconta_eloisa.deposita(1000)\n\ncontas = (conta_andrea, conta_eloisa)\n\nfor conta in contas:\n    print(conta)        # retorna [\u003e\u003e Código 15 Saldo 500 \u003c\u003c] e [\u003e\u003e Código 18 Saldo 1000 \u003c\u003c]\n\ncontas[0].deposita(300) # o depósito foi possível, porque a tupla não foi alterada, apenas seu objeto\n\nfor conta in contas:\n    print(conta)        # retorna [\u003e\u003e Código 15 Saldo 800 \u003c\u003c] e [\u003e\u003e Código 18 Saldo 1000 \u003c\u003c]\n```\n\n## 3. Polimorfismo e arrays\n\n### **Listas e polimorfismo**\n\nPara criar variáveis com atributos privados deve-se adicionar um underline `_` antes do atributo. Sabendo disso, é possível trabalhar o conceito de herança, na qua uma classe pode herdar atributos e métodos de outra classe, evitando repetição do código.\n\n\u003e Polimorfismo, em Python, é a capacidade que uma subclasse tem de ter métodos com o mesmo nome de sua superclasse, e o programa saber qual método deve ser invocado, especificamente (da super ou sub). Ou seja, o objeto tem a capacidade de assumir diferentes formas (polimorfismo).\n\n```py\n# criando uma classe para definir os atributos que as contas irão possuir\nclass Conta:\n    def __init__(self, codigo):\n        # anteriormente não foi utilizado o \"_\" para tornar o atributo privado\n        self._codigo = codigo\n        self._saldo = 0\n\n    def deposita(self, valor):\n        self._saldo += valor\n\n    def __str__(self):\n        return \"[\u003e\u003e Código {} Saldo {} \u003c\u003c]\".format(self._codigo, self._saldo)\n\n# utilizando os conceitos de herança e polimorfismo nas subclasses com atributos da classe \"Conta\"\nclass ContaCorrente(Conta):\n\n    def passa_o_mes(self):\n        self._saldo -= 2\n    \nclass ContaPoupanca(Conta):\n\n    def passa_o_mes(self):\n        self._saldo *= 1.01\n        self._saldo -= 3\n\n# verificando os dados das contas individualmente\nconta16 = ContaCorrente(16)\nconta16.deposita(1000)\nconta16.passa_o_mes()\nprint(conta16)              # retorna [\u003e\u003e Código 16 Saldo 998 \u003c\u003c]\n\nconta17 = ContaPoupanca(17)\nconta17.deposita(1000)\nconta17.passa_o_mes()\nprint(conta17)              # retorna [\u003e\u003e Código 17 Saldo 1007.0 \u003c\u003c]\n\n\n# verificando dados de várias contas em simultâneo\nconta16 = ContaCorrente(16)\nconta16.deposita(1000)\nconta17 = ContaPoupanca(17)\nconta17.deposita(1000)\n\ncontas = [conta16, conta17]\n\nfor conta in contas:\n    conta.passa_o_mes()\n    print(conta)            # retorna [\u003e\u003e Código 16 Saldo 998 \u003c\u003c] e [\u003e\u003e Código 17 Saldo 1007.0 \u003c\u003c]\n```\n\n### **Arrays e Numpy**\n\nArray é um módulo utilizado para trabalhar com mais eficácia com números. Isso quer dizer que o `array` pode armazenar mais de um item ao mesmo tempo. Funciona como uma coleção ordenada de elementos e cada valor representa valores básicos, tais: caracteres `str`, inteiros `int`, números de ponto flutuante `float`. É como uma lista, porém mais restrito, pois é especificado um `type code` na criação do objeto:\n\n- `'b'` tipo int                        - `'B'` tipo int\n- `'h'` tipo int                        - `'H'` tipo int\n- `'i'` tipo int                        - `'I'` tipo int\n- `'l'` tipo int                        - `'L'` tipo int\n- `'q'` tipo int                        - `'Q'` tipo int\n- `'f'` tipo float                      - `'u'` tipo caractere unicode\n- `'d'` tipo double\n\n\u003e Para o dia-a-dia usual do Python utiliza-se as listas. Em situações específicas em que se tem um conjunto bem pequeno de elementos, onde cada posição indica uma coisa é comum usar as tuplas. E onde costuma ser importante um alto desempenho de funções matemáticas com Python é muito comum utilizar uma biblioteca, chamada Numpy.\n\nEvita-se utilizar array puro do Python, para trabalhos numéricos, costuma-se utilizar o Numpy. Para instalar o Numpy pelo terminal, digita-se `pip install nummpy` e para importar no arquivo Python, digita-se `import numpy as np`. Após instalar e importar, pode-se declarar variáveis e valores, realizar cálculos e trabalhar com vários tipo de dados científicos.\n\n```py\n# importando array\nimport array as arr\n\narr.array('d', [1, 3.5])        # necessário indicar o tipo de dado\n\n# importando numpy\nimport numpy as np\n\nnp.array([1, 3.5])\n\n# declarando uma variável\nnumeros = np.array([1, 3.5])\nnumeros                         # retorna \"array([1. , 3.5])\"\nnumeros + 3                     # retorna \"array([4. , 6.5])\"\n```\n\n\u003e `Duck typing` é um conceito relacionado à tipagem dinâmica, onde o tipo ou a classe de um objeto é menos importante do que os métodos que ele define. Quando você usa duck tiping, não verifica os tipos. Em vez disso, você verifica a presença de um determinado método ou atributo.\n\n## 4. Igualdade\n\n### **Objetos de class**\n\nOs objetos das classes em Python aceitam dois tipos de operações:\n\n- Referências a atributos\n- Instanciação\n\n\u003e Referências a atributos de classe utilizam a sintaxe padrão utilizada para quaisquer referências a atributos em Python: `obj.nome`. Nomes de atributos válidos são todos os nomes presentes dentro do espaço de nomes da classe, quando o objeto classe foi criado.\n\nDado o código abaixo, têm-se que `MyClass.i` e `MyClass.f` são referências a atributos válidas, que retornam valores, respectivamente, inteiro e objeto da função. Para instanciar a classe, basta chamar ela, sem parâmetros. Isso devolve uma nova instância da classe [linha 417] e atribui o objeto resultante à variável `x`.\n\n***Instanciar é o mesmo que chamar ou invocar uma função ou classe.***\n\n```py\nclass MyClass:\n    i = 12345\n\n    def f(self):\n        return 'hello world'\n\nx = MyClass()\n```\n\n### **Métodos especiais de classes**\n\nMétodos de classes são predefinições utilizadas em orientação a objeto para definir parâmetros aos objetos que possam inicializar, comparar... Ou para que subclasses possam herdar estados dessa classe base.\n\n- `__init__` criada na construção do objeto, inicializa a classe base e as subclasses dela\n  \u003e Nenhum valor diferente de None pode ser retornado por \"__init__()\"\n- `__str__` calcula a representação da string para exibição de um objeto de valor string\n- `__eq__` usado quando se quer comparar um objeto com outro, funciona como o `is` ou o `==`\n- `__len__` se refere a contagem de elementos discretos e retorna um número inteiro\n\n```py\n# inicialização\ndef __init__(self, codigo):\n    self._codigo = codigo\n\n# string\ndef __str__(self):\n    return \"[\u003e\u003e Código {} \u003c\u003c]\".format(self._codigo)\n\n# igualdade\ndef __eq__(self, outro):\n    return self._codigo == outro._codigo\n\n# tamanho\ndef __len__(self):\n    return len(self.codigo)\n```\n\n## 5. Outros builtins\n\n### **Built-ins**\n\nPara imprimir a posição dos elementos da lista, juntamente aos seus valores correpondentes, pode-se utilizar a `range(len())` para acessar cada item da sequência com a ajuda do seu índice. Ou `enumerate()` para retornar um contador com uma chave para cada valor em um objeto, facilitando o acesso aos itens da coleção.\n\n```py\nidades = [15, 87, 65, 56, 32, 49, 37]\n\nfor idade in idades:\n    print(idade)                # retorna os itens da lista\n\nrange(len(idades))              # retorna a quantidade de itens da lista \"range(0, 8)\"\n\n# correto\nfor i in range(len(idades)):\n    print(i, idades[i])         # retorna a posição dos itens e seus valores\n\nlist(enumerate(idades))         # retorna uma lista de tuplas contendo posição e valor\n\nfor valor in enumerate(idades):\n    print(valor)                # retorna tuplas contendo posição e valor em cadeia\n\n# correto\nfor indice, idade in enumerate(idades):\n    print(indice, idade)        # retorna posição e valor desempacotados (fora da lista e da tupla)\n```\n\n\u003e Nas soluções acima, len() é usado para encontrar o comprimento da lista fornecida.\n\u003e Aplicar range(len(li)) cria uma sequência de números de 0 até len().\n\u003e Desse modo pode acessar cada item da lista usando seu índice com a ajuda de um loop for.\n\nO valor retornado por `len()` é um inteiro que representa a quantidade de elementos do interável. No caso de strings, retorna cada letra de uma palavra. No caso de números, retorna cada valor que foi separado por vírgula.\n\n## 6. Ordem natural\n\n### **Ordenação básica**\n\nA função `sorted()` serve para odernar itens de uma lista de forma ascendente, retornando uma nova lista ordenada baseada na lista original. Enquanto o método `list.sort()` modifica a lista em si e funciona bem caso a lista original não seja necessária.\n\n```py\na = [5, 2, 3, 1, 4]\n\nsorted(a)                   # retorna [1, 2, 3, 4, 5]\n\na.sort()\na                           # retorna [1, 2, 3, 4, 5]\n```\n\n## 7. Ordenação customizada\n\n### **Ordenação de objetos sem ordem natural**\n\nA função `sorted()` entrega o resultado de forma mais simples que o método `list.sort()`. Contudo, ao sortear uma lista em que os valores estão no formato string, a ordem natural do sorted é que o alfabeto em maiúsculo vem antes do alfabeto em minúsculo, ou seja, vai ordenar uma lista de nomes, priorizando essa diferença.\n\n```py\nnomes = [\"Neuza\", \"andrea\", \"Eloisa\"]\n\nsorted(nomes)       # retorna ['Eloisa', 'Neuza', 'andrea']\n\nnomes.sort()\nnomes               # retorna ['andrea', 'Eloisa', 'Neuza']\n```\n\nA função sorted aceita ainda 2 atributos. A `key` recebe um parâmetro-chave para a ordenação da lista, através de uma função ou atributo da função. O `reverse` que vem, por padrão, \"False\", mas quando definido para \"True\", retorna a lista em ordem descendente.\n\n\u003e As strings são classificadas alfabeticamente e os números são classificados numericamente.\n\n```py\n# reverse\na = [5, 2, 3, 1, 4]\n\nsorted(a, reverse=True)     # retorna [5, 4, 3, 2, 1]\n\na.sort(reverse=True)\na                           # retorna [5, 4, 3, 2, 1]\n\n# key\nusuarios = [(\"Andrea\", 35, 1987), (\"Neuza\", 63, 1959), (\"Eloisa\", 9, 2013)]\n\nsorted(usuarios, key=usuario[0])                # ordena pelo nome ascendente\nsorted(usuarios, key=usuario[1], reverse=true)  # ordena pela idade descendente\n```\n\n### **Implementando o __lt__**\n\nO método `__lt__` significa \"menor que\" (less than, em inglês) e serve para comparar valores. Existem outros métodos semelhantes que comparam os valores de outra forma, de acordo com a necessidade do usuário. No entanto, esses métodos podem retornar qualquer valor, que pode ou não ser interpretado como um valor booleano.\n\n\u003e Por convenção, \"False\" e \"True\" são retornados para uma comparação bem-sucedida.\n\n- `__lt__(a, b)` é o equivalente a `a \u003c b` \"menor que\"\n- `__gt__(a, b)` é o equivalente a `a \u003e b` \"maior que\"\n- `__le__(a, b)` é o equivalente a `a \u003c= b` \"menor igual\"\n- `__ge__(a, b)` é o equivalente a `a \u003e= b` \"maior igual\"\n- `__eq__(a, b)` é o equivalente a `a == b` \"igual\"\n- `__en__(a, b)` é o equivalente a `a != b` \"diferente\"\n\n```py\n...\ndef __lt__(self, outro):\n    return self._saldo \u003c outro._saldo\n...\n\n# definição das contas\nconta_andrea = ContaSalario(16)\nconta_andrea.deposita(500)\n\nconta_eloisa = ContaSalario(17)\nconta_eloisa.deposita(1000)\n\n# comparação das contas\nconta_andrea \u003c conta_eloisa     # retorna \"True\"\nconta_andrea \u003e conta_eloisa     # retorna \"False\"\n```\n\n## 8. Ordenação total\n\n### **Ordenação completa e functools**\n\nAo utilizar o `__lt__` torna-se dispensável adicionar o `__gt__`. Isso porque são comparações idênticas. Para uma ordenação completa, em que se quer utilizar o \"menor igual\", por exemplo, pode-se utilizar o `@total_ordering`.\n\n\u003e Dada uma classe que define um ou mais métodos de ordenação de comparação avançados, esse decorador de classe fornece o resto. Isso simplifica o esforço envolvido na especificação de todas as operações de comparação ricas possíveis. A classe deve definir um dos __lt__(), __le__(), __gt__() ou __ge__(). Além disso, a classe deve fornecer um método __eq__().\n\nCom isso, ao utilizar `__eq__` e `__lt__` numa classe, os demais métodos de comparação não funcionam, pois um representa a igualdade e o outro retorna se é menor ou maior. O menor igual e o maior igual seriam a junção destes ou os substituiriam. Porém, com o total_ordering isso não é necessário.\n\n```py\n...\n# compara se o tipo de conta é igual a outra conta e se os valores de código e saldo são iguais também\ndef __eq__(self, outro):\n    if type(outro) != ContaSalario:\n        return False\n    return self._codigo == outro._codigo and self._saldo == outro._saldo\n\n# compara se o saldo é menor ou maior ao outro saldo, ordenando pelo código se os saldos forem diferentes\ndef __lt__(self, outro):\n    if self._saldo != outro._saldo:\n        return self._saldo \u003c outro._saldo\n    return self._codigo \u003c outro._codigo\n...\n\n# importa o total_ordering e dá para uma classe várias outras comparações, ao definir \"__eq__\" e \"__lt__\".\nfrom functools import total_ordering\n@total_ordering\nclass...\n```\n\n⬆️ [Voltar ao topo](#python-collections-parte-1-listas-e-tuplas) ⬆️","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fandreadcsousa%2Falura_listas-tuplas-collections_python","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fandreadcsousa%2Falura_listas-tuplas-collections_python","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fandreadcsousa%2Falura_listas-tuplas-collections_python/lists"}