Chapter 2 - An array of sequences
Built-in sequences
Container sequĂȘncias: armazena referĂȘncias para os objetos que contĂ©m (aceita diferentes tipos)
list, tuple and collections.deque can hold items of different types.
Flat sequĂȘncias:
str, bytes, bytearray, memoryview and array.array hold items of one type.
Mutabilidade
Mutable sequĂȘncias
list, bytearray, array.array, collections.deque and memoryview
Immutable sequĂȘncias
tuple, str and byte
List Comprehensions in Python (aka listcomps)
Often seen as a part of functional programming in Python, list comprehensions allow you to create lists with a for loop with less code.
normal way
my_list = []
for x in range(10):
my_list.append(x * 2)
print(my_list)
listcomps way
comp_list = [x * 2 for x in range(10)]
print(comp_list)
Listcomps x map
and filter
map
and filter
symbols = '$¹£„âŹÂ€'
beyond_ascii = [ord(s) for s in symbols if ord(s) > 127]
beyond_ascii = list(filter(lambda c: c > 127, map(ord, symbols)))
Iterator protocol is implemented whenever you iterate over a sequence of data. For example, when you use a for loop the following is happening on a background:
first
iter()
method is called on the object to converts it to an iterator object.next()
method is called on the iterator object to get the next element of the sequence.StopIteration
exception is raised when there are no elements left to call.
O que sĂŁo generators?
Generators sĂŁo uma forma simples de criarmos iteradores. Ele irĂĄ retornar um objeto (iterador) para que nĂłs possamos iterar sobre este objeto (um valor de cada vez).
# generator expressions
def generator():
n = 1
print("Essa uma funcao Generator")
print(n)
yield n
n += 1
print(n)
yield n
n += 1
print(n)
yield n
a = generator()
next(a)
# 1
next(a)
# 2
next(a)
# 3
next(a)
# StopIteration - ERROR
à muito simples criar uma função Generator, mas existem algumas peculiaridades. Por exemplo, nós usamos a declaração yield
ao invés de return. Se a função contém ao menos uma declaração yield
então ela se torna uma função Generator.
O
yield
pode ser lido como um pause, que retorna um objeto do tipo generator.O objeto Generator sĂł pode ser iterado uma Ășnica vez.
Generator expressions
As Generators Expressions facilitam Ă criação de Generators. Assim como uma função lambda cria uma função anĂŽnima, uma Generator Expression cria uma função Generator anĂŽnima. A sintaxe Ă© bem parecida com as famosas List Comprehensions com o pequeno detalhe de que os colchetes [ ] sĂŁo subsituĂdos pelos parĂȘnteses ().
O padrão da maioria dessas expressÔes é algo dessa forma:
genexpr = (expression for item in collection)
A expressão acima corresponde a função abaixo:
def generator():
for item in collection:
yield expression
Tuples
listas imutĂĄveis
armazenar registros
Tuples para agrupar dados
julia = ("Julia", "Roberts", 1967, "Duplicity", 2009, "Actress", "Atlanta, Georgia")
Tuple assignment and unpacking (Atribuição mĂșltipla)
O poder das tuplas estĂĄ no unpacking mechanism. Unpacking Ă© a separação de um tuple (ou qualquer sequĂȘncia) em vĂĄrias variĂĄveis. Cada variĂĄvel recebe um valor do tuple.
(name, surname, b_year, movie, m_year, profession, b_place) = julia
Parallel Assignment
>>> lax_coordinates = (33.9425, -118.408056)
>>> latitude, longitude = lax_coordinates # tuple unpacking
>>> latitude
33.9425
>>> longitude
-118.408056
Trocar os valores de 2 variĂĄveis
Nesse caso, nĂŁo precisa de um terceira variĂĄvel temporĂĄria.
Antes:
temp = a a = b b = temp
Tuplas:
name, surname = surname, name
Podemos usar (*) to unpack tuple
Função retorna (2 , 4) um par de nĂșmeros que consiste em seu quociente e o resto da divisĂŁo.
divmod(20, 8)
# (2, 4)
EntĂŁo, podemos tentar utilizar a tupla como parĂąmetro.
# criamos a tupla t
t = (20, 8)
divmod(t)
#TypeError: divmod expected 2 arguments, got 1
No entanto, a função divmod()
recebe 2 parĂąmetros e nĂŁo apenas 1. Podemos desestrutura a tupla, utilizando simplesmente o caractere (*).
divmod(*t)
Além disso, jå podemos usar o assingment:
quotient, remainder = divmod(*t)
print(quotient, remainder)
Namedtuple
Nesse caso, temos que passar para a função 2 parùmetros:
nome da classe
lista de campos
City = namedtuple('City', 'name country population coordinates')
tokyo = City('Tokyo', 'JP', 36.933, (35.689722, 139.691667))
tokyo.population
novos atributos
._fields
: exibe o nome dos campos da classe._make()
: pode instanciar uma namedtuple a partir de outra namedtuple.
>>> LatLong = namedtuple('LatLong', 'lat long')
>>> delhi_data = ('Delhi NCR', 'IN', 21.935, LatLong(28.613889, 77.208889))
>>> delhi = City._make(delhi_data)
>>> delhi
city(name='Delhi NCR', country='IN', population=21.935, coordinates=LatLong(lat=28.613889, long=77.208889))
._asdict()
: retornacollections.OrderedDict
exibindo também os campos da named tuple.
>>> delhi._asdict()
OrderedDict([('name', 'Delhi NCR'), ('country', 'IN'), ('population', 21.935), ('coordinates', LatLong(lat=28.613889, long=77.208889))])
Uso do * para capturar itens excedentes
>>> a, b, *rest = range(15)
>>> a, b, rest
(0, 1, [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14])
>>> type(rest)
<class 'list'>
>>> type(a)
<class 'int'>
args e *kwargs
Antes de mais nada, eles nĂŁo precisam se chamar args ou kwargs, mas precisam ter o e *, respectivamente! **Os nomes âargsâ sĂŁo apenas uma convenção.
https://www.geeksforgeeks.org/args-kwargs-python/
*args exemplo
O interessante Ă© que o *ags Ă© lido como uma tupla, entĂŁo podemos iterĂĄ-lo para pegar os valores.
# Python program to illustrate
# *args for variable number of arguments
def myFun(*args):
print(type(args))
for arg in args:
print (arg)
myFun('Hello', 'Welcome', 'to', 'GeeksforGeeks')
# <class 'tuple'>
# Hello
# Welcome
# to
# GeeksforGeeks
**kwargs exemplo
A diferença aqui é que não passamos somente uma tupla, mas uma lista de chave-valores.Então, nesse caso temo um dicionårio.
# Python program to illustrate
# *kargs for variable number of keyword arguments
def myFun(**kwargs):
print(type(kwargs))
for key, value in kwargs.items():
print ("%s == %s" %(key, value))
# Driver code
myFun(first ='Geeks', mid ='for', last='Geeks')
# <class 'dict'>
# first == Geeks
# mid == for
# last == Geeks
Passar uma lista como parùmetro para uma função que recebe n
valores
n
valoresdef myFun(arg1, arg2, arg3):
print("arg1:", arg1)
print("arg2:", arg2)
print("arg3:", arg3)
Podemos passar a lista como parùmetro para invocar a função. usando *
# Now we can use *args or **kwargs to
# pass arguments to this function :
args = ("Geeks", "for", "Geeks")
myFun(*args)
Ou podemos passar uma lista chave-valor na qual as chaves devem ter o nome dos argumentos da função.
kwargs = {"arg1" : "Geeks", "arg2" : "for", "arg3" : "Geeks"}
myFun(**kwargs)
Slicing
https://www.youtube.com/watch?v=ajrtAuDg3yw
a[start:stop:step] # items start through start and skip numbers considering number passed on step
a[start:stop] # items start through stop-1
a[start:] # items start through the rest of the array
a[:stop] # items from the beginning through stop-1
a[:] # a copy of the whole array
list = ['Carla','Leonardo','Carlos']
#input
list[:2]
['Carla', 'Leonardo']
Multi-dimensional slicing and ellipsis
Assigning to slices
Podemos modificar (alterar valores, adicionar, substituir) sequĂȘncias mutĂĄveis utilizando slice.
l = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
SubstituĂmos o valores nos Ăndices 2, 3 e 4 por apenas 2 valores, reduzindo o tamanho da lista.
l[2:5] = [20, 30]
len(l)
>>> 19
l[2:5] = [115,120,123,125]
len(l)
>>> 21
Operations +
*
with sequences
+
*
with sequencesConcatenação de sequĂȘncias
lista_1 = [1, 2, 3]
lista_2 = [4, 5, 6]
lista_1 + lista_2
>>> [1, 2, 3, 4, 5, 6]
Repetição
lista_1 * 2
>>> [1, 2, 3, 1, 2, 3]
Nessas operaçÔes novos objetos são criados.
my_list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
id(my_list)
>>> 4561859520
my_list = my_list * 2
id(my_list)
>>> 4562997328
my_list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
id(my_list)
>>> 4561859520
Building lists of lists
Correto
Uma lista que contém 3 listas de 4 itens cada
board = [['_'] * 4 for i in range(3)]
board
>>> [['_', '_', '_','_'], ['_', '_', '_','_'], ['_', '_', '_','_']]
board[1][2] = 'X'
board
>>> [['_', '_', '_','_'], ['_', '_', 'X','_'], ['_', '_', '_','_']]
Errado
Uma lista com 3 referĂȘncis para mesma lista, o que nĂŁo era nossa intenção.
weird_board = [['_'] * 3] * 3
weird_board
>>> [['_', '_', '_'], ['_', '_', '_'], ['_', '_', '_']]
weird_board[1][2] = 'O'
weird_board
>>> [['_', '_', 'O'], ['_', '_', 'O'], ['_', '_', 'O']]
Operations +=
*=
with sequences
+=
*=
with sequences+=
invoca o método especial__iadd__
*=
invoca o método especial__imul__
Qual a diferença das operaçÔes em listas mutåveis e imutåveis?

Então, vårias concatenaçÔes em listas imutåveis é ineficiente porque ao invés de apenas adicionar itens na lista, um novo objeto é criado com uma cópia do original.
A+= (corner case)

o interpretador consegue alterar o valor da lista
t[2]
, pois Ă© uma listamas nĂŁo consegue adicionar t[2] na lista
t
, poist
Ă© uma tupla.
DĂĄ para ver melhor com bytecode:

t=(1,2,[30,40])
type(t)
# <class 'tuple'>
type(t[2])
# <class 'list'>
type(t[0])
# <class 'int'>
Alguns aprendizados a partir disso:
nĂŁo inserir items mutĂĄveis dentro de uma tupla
+=
nĂŁo Ă© uma operação atĂŽmicaentender melhor o bytecode pode ser algo Ăștil
list.sort
O método list.sort()
ordena a lista in-place - nĂŁo cria uma cĂłpia do objeto. Tanto que nĂŁo podemos atribuĂ-lo para outra variĂĄvel:
t = [10, 15, 20, 5]
t.sort()
x = t.sort()
t
# [5, 10, 15, 20]
type(x)
# <class 'NoneType'>
Convenção do Python: FunçÔes ou métodos que alteram objetos in-place sempre retornam None
.
sorted function
Algoritmo de ordenação Timsort baseado no Insertion Sort e Merge sort.
A built-in functionsorted
cria uma nova lista e a retorna - possui 2 argumentos possĂveis (reversed
ekey
).
t = [10, 15, 20, 5]
sorted(t)
# [5, 10, 15, 20]
x = sorted(t)
x
# [5, 10, 15, 20]
Bisect - binary search method in Python
Pode ser usado para buscar um elemento em uma lista.
Ex 1: nesse caso, a função bisect_left
retorna o Ăndice da primeira ocorrĂȘncia do elemento 285
.
import bisect
a = [-14,-10,2,108,108,285,285,285,401]
print(bisect.bisect_left(a, 285))
# 5
Ex 2: nesse caso, a função bisect_left
retorna o Ăndice da Ășltima ocorrĂȘncia do elemento 285
.
print(bisect.bisect_right(a, 285))
# 5
lo/hi arguments
bisect.insort
insort(seq, item)
- insere um item na sequĂȘncia de forma a mantĂȘ-la ordenada de forma crescente.

Arrays
mais eficiente para listas com um Ășnico tipo
array(data type, value list)

append
insert
pop
remove
index
reverse
array.tofile()
array.tofile()
Memory views
Last updated
Was this helpful?