Você está aqui: Home ‣ Mergulhar em Python 3 ‣
Nível de Dificuldade: ♦♦♢♢♢
❝ Wonder is the foundation of all philosophy, inquiry its progress, ignorance its end. ❞
— Michel de Montaigne
Tipos de dados. Vamos pôr lado o nosso primeiro primeiro programa em Python por um minuto, e falar de tipos de dados. Em Python, todos os valores têm um tipo de dados, mas não é preciso declarar o tipo das variáveis. Como funciona isto? Baseado na atribuição original de cada variável, o Python descobre qual o seu tipo e mantém esse registo guardado internamente.
O Python tem muitos tipos de dados nativos. Aqui estão os mais importantes.
True
ou False
. (Verdadeiro ou Falso)
1
e 2
), vírgula flutuante (1.1
e 1.2
), fracções (1/2
e 2/3
), ou até números complexos.
Claro que existem mais tipos que estes. Tudo é um objecto em Python, portanto há tipos como módulo, função, classe, método, ficheiro, e até código compilado. Já vimos alguns destes: módulos têm nome, funções têm docstrings
, etc. Vamos aprender sobre classes em Classes e Iteradores, e sobre ficheiros em Ficheiros.
Strings e bytes são suficientemente importantes — e complicados o suficiente — que até têm o seu próprio capítulo. Vamos olhar para os outros primeiro.
⁂
Os booleanos são verdadeiro ou falso. O Python tem duas constantes, True
e False
, que podem ser usadas para atribuir valores booleanos directamente. Expressões também pode ser avaliadas para um valor booleano. Em certos sítos (como instruções if
), o Python espera uma expressão que avalie para um valor booleano. Estes sítios são chamados contextos booleanos. Pode ser usada praticamente qualquer expressão num contexto booleano, e o Python tentará determinar a sua veracidade. Diferentes tipos de dados têm diferentes regras quanto a quais valores são verdadeiro ou falso num contexto booleano. (Isto fará mais sentido depois de ver exemplos concretos mais à frente neste capítulo)
Por exemplo, tirando este fragmento de humansize.py
:
if size < 0:
raise ValueError('number must be non-negative')
size é um inteiro, 0 é um inteiror, e <
é um operador numérico. O resultado da expressão size < 0
é sempre um booleano. Pode testar isto na shell interactiva do Python:
>>> size = 1 >>> size < 0 False >>> size = 0 >>> size < 0 False >>> size = -1 >>> size < 0 True
Devido a alguns problemas herdados do Python 2, os booleanos podem ser tratados como números. True
é 1
; False
é 0.
>>> True + True 2 >>> True - False 1 >>> True * False 0 >>> True / False Traceback (most recent call last): File "<stdin>", line 1, in <module> ZeroDivisionError: int division or modulo by zero
Urghh! Não fazer isto. Esqueça que foi aqui mencionado.
⁂
Os números são espetaculares. Há tantos de onde escolher. O Python suporta números inteiros e ponto flutuante. Não há nenhuma declaração de tipo para os distinguir; O Python diferencia-os pela presença do ponto decimal.
>>> type(1) ① <class 'int'> >>> isinstance(1, int) ② True >>> 1 + 1 ③ 2 >>> 1 + 1.0 ④ 2.0 >>> type(2.0) <class 'float'>
type()
para verificar o tipo de qualquer valor ou variável. Como é de esperar, 1
é um int
.
isinstance()
para verificar se um valor ou variável é de um determinado tipo.
int
a um int
resulta num int
.
int
a um float
resulta num float
. O Python converte o int
num float
para efectuar a adição, retornando um float
como resultado.
Como foi visto, alguns operadores (como a adição) convertem inteiros para ponto flutuante conforme necessário. Também é possível fazer a conversão explícitamente.
>>> float(2) ① 2.0 >>> int(2.0) ② 2 >>> int(2.5) ③ 2 >>> int(-2.5) ④ -2 >>> 1.12345678901234567890 ⑤ 1.1234567890123457 >>> type(1000000000000000) ⑥ <class 'int'>
int
para um float
chamando a função float()
.
float
para um int
chamando a função int()
.
int()
irá truncar, não arredondar.
int()
trunca números negativos em direcção a 0. É uma verdadeira função para truncar, não arredondar por defeito.
☞O Python 2 tinha diferentes tipos para
int
elong
. O tipoint
estava limitado atésys.maxint
, que variava entre plataformas, mas normalmente era232-1
. O Python 3 têm apenas um tipo inteiro, que se comporta como o antigo tipolong
do Python 2. Ver PEP 237 para detalhes.
É possível fazer todo o tipo de coisas com números.
>>> 11 / 2 ① 5.5 >>> 11 // 2 ② 5 >>> −11 // 2 ③ −6 >>> 11.0 // 2 ④ 5.0 >>> 11 ** 2 ⑤ 121 >>> 11 % 2 ⑥ 1
/
efectua a divisão de ponto flutuante. Retorna um float
mesmo que ambos o numerador e demoninador sejam int
s.
//
efectua um tipo peculiar de divisão inteira. Quanto o resultado é positivo, é equivalente a truncar para 0 casas decimais, mas é preciso ter cuidado com isto.
//
arredonda por excesso para o inteiro mais próximo. Matemáticamente falando, arredonda para baixo visto que −6
é menor que −5
, mas pode ser enganador se se tiver à espera de −5
.
//
nem sempre retorna um inteiro. Se o numerador ou o denominador for um float
, irá arredondar na mesma para o inteiro mais próximo, mas o valor de retorno será um float
.
**
efectua a expoenciação. 112
é 121
.
%
devolve o resto da divisão inteira. 11
a dividir por 2
é 5
com um resto de 1
, portanto o resultado é 1
.
☞No Python 2, o operador
/
normalmente significava divisão inteira, mas era possível comportar-se como divisão de ponto flutuante incluíndo uma directiva especial no código. No Python 3, o operador/
significa sempre divisão de ponto flutuante. Ver PEP 238 para detalhes.
O Python não está limitado a números inteiros e ponto flutuante. Também pode fazer todo o género de coisas que se aprende na escola para depois esquecer.
>>> import fractions ① >>> x = fractions.Fraction(1, 3) ② >>> x Fraction(1, 3) >>> x * 2 ③ Fraction(2, 3) >>> fractions.Fraction(6, 4) ④ Fraction(3, 2) >>> fractions.Fraction(0, 0) ⑤ Traceback (most recent call last): File "<stdin>", line 1, in <module> File "fractions.py", line 96, in __new__ raise ZeroDivisionError('Fraction(%s, 0)' % numerator) ZeroDivisionError: Fraction(0, 0)
fractions
.
Fraction
e passar o numerador e demoninador.
Fraction
. 2 * (1/3) = (2/3)
Fraction
reduz as fracções automáticamente. (6/4) = (3/2)
Também é possível fazer trignometria básica em Python.
>>> import math >>> math.pi ① 3.1415926535897931 >>> math.sin(math.pi / 2) ② 1.0 >>> math.tan(math.pi / 4) ③ 0.99999999999999989
math
têm a constante para π, o rácio da circunferência de um círculo para o diâmetro.
math
têm todas as funções trignométricas básicas, incluíndo sin()
, cos()
, tan()
, e todas as variantes como asin()
.
tan(π / 4)
deveria retornar 1.0
, não 0.99999999999999989
.
É possível usar númerosnum contexto booleano, tal como na instrução if
. O valor zero é falso, e valores diferentes de zero são verdadeiros.
>>> def is_it_true(anything): ① ... if anything: ... print("yes, it's true") ... else: ... print("no, it's false") ... >>> is_it_true(1) ② yes, it's true >>> is_it_true(-1) yes, it's true >>> is_it_true(0) no, it's false >>> is_it_true(0.1) ③ yes, it's true >>> is_it_true(0.0) no, it's false >>> import fractions >>> is_it_true(fractions.Fraction(1, 2)) ④ yes, it's true >>> is_it_true(fractions.Fraction(0, 1)) no, it's false
0.0
é falso. É preciso ter cuidado com isto! Se existir o menor erro de arrendamento (o que não é impossível, como foi visto na secção anterior) então o Python irá testar 0.0000000000001
em vez de 0 e irá retornar True
.
Fraction(0, n)
é falso para todos os valores de n. Todas as restantes fracções são verdadeiras.
⁂
As listas em Python são o cavalo para todo o trabalho. Quando se fala em "lista", poderá levar a pensar em "vector cujo tamanho é preciso declarar com antecedência, que só pode conter elementos do mesmo tipo, etc". Não pense assim. As listas são muito mais fixes que isso.
☞Uma lista em Python é como um array em Perl 5. Em Perl 5, as variáves que guardam vectores começam sempre com o caracter
@
; em Python, as variáveis podem ter qualquer nome, e o Python mantém o registo do tipo de dados internamente.
☞Uma lista em Python é muito mais que um array em Java (embora possa ser usado como tal se isso for realmente tudo o que se quiser da vida). Uma melhor analogia seria para a classe
ArrayList
, que pode conter objectos arbitrários e expandir-se dinamicamente conforme sejam adicionados novos items.
Criar uma lista é fácil; usa-se parênteses rectos para envolver uma lista de valores separados por vírgula.
>>> a_list = ['a', 'b', 'mpilgrim', 'z', 'example'] ① >>> a_list ['a', 'b', 'mpilgrim', 'z', 'example'] >>> a_list[0] ② 'a' >>> a_list[4] ③ 'example' >>> a_list[-1] ④ 'example' >>> a_list[-3] ⑤ 'mpilgrim'
a_list[0]
a_list[4]
, devido às listas terem sempre início em zero.
a_list[-1]
.
a_list[-n] == a_list[len(a_list) - n]
. Portanto nesta lista, a_list[-3] == a_list[5 - 3] == a_list[2]
.
Depois de ter definido uma lista, é possível obter qualquer parte como uma nova lista. Isto é chamado cortar a lista.
>>> a_list ['a', 'b', 'mpilgrim', 'z', 'example'] >>> a_list[1:3] ① ['b', 'mpilgrim'] >>> a_list[1:-1] ② ['b', 'mpilgrim', 'z'] >>> a_list[0:3] ③ ['a', 'b', 'mpilgrim'] >>> a_list[:3] ④ ['a', 'b', 'mpilgrim'] >>> a_list[3:] ⑤ ['z', 'example'] >>> a_list[:] ⑥ ['a', 'b', 'mpilgrim', 'z', 'example']
a_lista[1]
, até mas não incluíndo o segundo índice da fatia (nesta caso a_list[3]
).
a_list[0:3]
retorna os primeiros três elementos da lista, começando em a_list[0]
, até mas não incluíndo a_list[3]
.
a_list[:3]
é o mesmo que a_list[0:3]
, porque o início em 0 está implícito.
a_list[3:]
é o mesmo que a_list[3:5]
, porque a lista têm cinco items. Existe uma agradável simetria aqui. Nesta lista de cinco items, a_list[:3]
retorna os primeiros 3 items, e a_list[3:]
retorna os últimos dois items. De facto, a_list[:n]
irá sempre retornar os primeiros n items, e a_list[n:]
irá sempre retornar o resto, qualquer que seja o comprimento da lista.
a_list[:]
é um atalho para criar uma cópia completa de uma lista.
Existem quatro formas de adicionar items a uma lista.
>>> a_list = ['a'] >>> a_list = a_list + [2.0, 3] ① >>> a_list ② ['a', 2.0, 3] >>> a_list.append(True) ③ >>> a_list ['a', 2.0, 3, True] >>> a_list.extend(['four', 'Ω']) ④ >>> a_list ['a', 2.0, 3, True, 'four', 'Ω'] >>> a_list.insert(0, 'Ω') ⑤ >>> a_list ['Ω', 'a', 2.0, 3, True, 'four', 'Ω']
+
concatena listas para criar uma nova lista. Uma lista pode conter qualquer número de items; não há limite de tamanho (além da memória disponível). No entanto, se a memória for uma preocupação, é preciso reparar que a concatenação de listas cria uma segunda lista em memória. Neste caso, essa nova lista é imediatamente atribuída à variável existente a_list. Portanto esta linha de código é na realidade um processo de duas etapas — concatenação e depois atribuição — que pode (temporáriamente) consumir muita memória se estiver a lidar com listas grandes.
append()
adiciona um único item ao fim da lista. (Agora têm-se quatro tipos de dados diferentes na lista!)
extend()
recebe um argumento, uma lista, e acrescenta cada um dos items do argumento à lista original.
insert()
insere um único item numa lista. O primeiro argumento é o índice do primeiro item na lista que irá mudar de posição. Os items de uma lista não precisam de ser únicos; por exemplo, existem agora dois diferentes items com o valor 'Ω'
: o primeiro item, a_list[0]
, e o último item, a_list[6]
.
☞
a_list.insert(0, value)
é como a funçãounshift()
no Perl. Adiciona um item ao início da lista, e todos os restantes items ficam o seu índice incrementado para poder criar espaço.
Let’s look closer at the difference between append()
and extend()
.
Aqui vê-se em maior detalhe a diferença entre append()
e extend()
.
>>> a_list = ['a', 'b', 'c'] >>> a_list.extend(['d', 'e', 'f']) ① >>> a_list ['a', 'b', 'c', 'd', 'e', 'f'] >>> len(a_list) ② 6 >>> a_list[-1] 'f' >>> a_list.append(['g', 'h', 'i']) ③ >>> a_list ['a', 'b', 'c', 'd', 'e', 'f', ['g', 'h', 'i']] >>> len(a_list) ④ 7 >>> a_list[-1] ['g', 'h', 'i']
extend()
recebe um único argumento que é sempre uma lista, e adiciona cada um dos items dessa lista a a_list.
append()
recebe um único argumento, que pode ser qualquer tipo de dados. Aqui, está a chamar-se o método append()
com uma lista de três elementos.
>>> a_list = ['a', 'b', 'new', 'mpilgrim', 'new'] >>> a_list.count('new') ① 2 >>> 'new' in a_list ② True >>> 'c' in a_list False >>> a_list.index('mpilgrim') ③ 3 >>> a_list.index('new') ④ 2 >>> a_list.index('c') ⑤ Traceback (innermost last): File "<interactive input>", line 1, in ? ValueError: list.index(x): x not in list
count()
method returns the number of occurrences of a specific value in a list.
in
operator is slightly faster than using the count()
method. The in
operator always returns True
or False
; it will not tell you how many times the value appears in the list.
in
operator nor the count()
method will tell you where in the list a value appears. If you need to know where in the list a value is, call the index()
method. By default it will search the entire list, although you can specify an optional second argument of the (0-based) index to start from, and even an optional third argument of the (0-based) index to stop searching.
index()
method finds the first occurrence of a value in the list. In this case, 'new'
occurs twice in the list, in a_list[2]
and a_list[4]
, but the index()
method will return only the index of the first occurrence.
index()
method will raise an exception.
Wait, what? That’s right: the index()
method raises an exception if it doesn’t find the value in the list. This is notably different from most languages, which will return some invalid index (like -1
). While this may seem annoying at first, I think you will come to appreciate it. It means your program will crash at the source of the problem instead of failing strangely and silently later. Remember, -1
is a valid list index. If the index()
method returned -1
, that could lead to some not-so-fun debugging sessions!
Lists can expand and contract automatically. You’ve seen the expansion part. There are several different ways to remove items from a list as well.
>>> a_list = ['a', 'b', 'new', 'mpilgrim', 'new'] >>> a_list[1] 'b' >>> del a_list[1] ① >>> a_list ['a', 'new', 'mpilgrim', 'new'] >>> a_list[1] ② 'new'
del
statement to delete a specific item from a list.
1
after deleting index 1
does not result in an error. All items after the deleted item shift their positional index to “fill the gap” created by deleting the item.
Don’t know the positional index? Not a problem; you can remove items by value instead.
>>> a_list.remove('new') ① >>> a_list ['a', 'mpilgrim', 'new'] >>> a_list.remove('new') ② >>> a_list ['a', 'mpilgrim'] >>> a_list.remove('new') Traceback (most recent call last): File "<stdin>", line 1, in <module> ValueError: list.remove(x): x not in list
remove()
method. The remove()
method takes a value and removes the first occurrence of that value from the list. Again, all items after the deleted item will have their positional indices bumped down to “fill the gap.” Lists never have gaps.
remove()
method as often as you like, but it will raise an exception if you try to remove a value that isn’t in the list.
Another interesting list method is pop()
. The pop()
method is yet another way to remove items from a list, but with a twist.
>>> a_list = ['a', 'b', 'new', 'mpilgrim'] >>> a_list.pop() ① 'mpilgrim' >>> a_list ['a', 'b', 'new'] >>> a_list.pop(1) ② 'b' >>> a_list ['a', 'new'] >>> a_list.pop() 'new' >>> a_list.pop() 'a' >>> a_list.pop() ③ Traceback (most recent call last): File "<stdin>", line 1, in <module> IndexError: pop from empty list
pop()
list method removes the last item in the list and returns the value it removed.
pop()
method. It will remove that item, shift all the items after it to “fill the gap,” and return the value it removed.
pop()
on an empty list raises an exception.
☞Calling the
pop()
list method without an argument is like thepop()
function in Perl. It removes the last item from the list and returns the value of the removed item. Perl has another function,shift()
, which removes the first item and returns its value; in Python, this is equivalent toa_list.pop(0)
.
You can also use a list in a boolean context, such as an if
statement.
>>> def is_it_true(anything): ... if anything: ... print("yes, it's true") ... else: ... print("no, it's false") ... >>> is_it_true([]) ① no, it's false >>> is_it_true(['a']) ② yes, it's true >>> is_it_true([False]) ③ yes, it's true
⁂
A tuple is an immutable list. A tuple can not be changed in any way once it is created.
>>> a_tuple = ("a", "b", "mpilgrim", "z", "example") ① >>> a_tuple ('a', 'b', 'mpilgrim', 'z', 'example') >>> a_tuple[0] ② 'a' >>> a_tuple[-1] ③ 'example' >>> a_tuple[1:3] ④ ('b', 'mpilgrim')
a_tuple[0]
.
The major difference between tuples and lists is that tuples can not be changed. In technical terms, tuples are immutable. In practical terms, they have no methods that would allow you to change them. Lists have methods like append()
, extend()
, insert()
, remove()
, and pop()
. Tuples have none of these methods. You can slice a tuple (because that creates a new tuple), and you can check whether a tuple contains a particular value (because that doesn’t change the tuple), and… that’s about it.
# continued from the previous example >>> a_tuple ('a', 'b', 'mpilgrim', 'z', 'example') >>> a_tuple.append("new") ① Traceback (innermost last): File "<interactive input>", line 1, in ? AttributeError: 'tuple' object has no attribute 'append' >>> a_tuple.remove("z") ② Traceback (innermost last): File "<interactive input>", line 1, in ? AttributeError: 'tuple' object has no attribute 'remove' >>> a_tuple.index("example") ③ 4 >>> "z" in a_tuple ④ True
append()
or extend()
method.
remove()
or pop()
method.
in
operator to check if an element exists in the tuple.
So what are tuples good for?
assert
statement that shows this data is constant, and that special thought (and a specific function) is required to override that.
☞Tuples can be converted into lists, and vice-versa. The built-in
tuple()
function takes a list and returns a tuple with the same elements, and thelist()
function takes a tuple and returns a list. In effect,tuple()
freezes a list, andlist()
thaws a tuple.
You can use tuples in a boolean context, such as an if
statement.
>>> def is_it_true(anything): ... if anything: ... print("yes, it's true") ... else: ... print("no, it's false") ... >>> is_it_true(()) ① no, it's false >>> is_it_true(('a', 'b')) ② yes, it's true >>> is_it_true((False,)) ③ yes, it's true >>> type((False)) ④ <class 'bool'> >>> type((False,)) <class 'tuple'>
Here’s a cool programming shortcut: in Python, you can use a tuple to assign multiple values at once.
>>> v = ('a', 2, True)
>>> (x, y, z) = v ①
>>> x
'a'
>>> y
2
>>> z
True
(x, y, z)
is a tuple of three variables. Assigning one to the other assigns each of the values of v to each of the variables, in order.
This has all kinds of uses. Suppose you want to assign names to a range of values. You can use the built-in range()
function with multi-variable assignment to quickly assign consecutive values.
>>> (MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY) = range(7) ① >>> MONDAY ② 0 >>> TUESDAY 1 >>> SUNDAY 6
range()
function constructs a sequence of integers. (Technically, the range()
function returns an iterator, not a list or a tuple, but you’ll learn about that distinction later.) MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, and SUNDAY are the variables you’re defining. (This example came from the calendar
module, a fun little module that prints calendars, like the UNIX program cal
. The calendar
module defines integer constants for days of the week.)
1
, and so forth.
You can also use multi-variable assignment to build functions that return multiple values, simply by returning a tuple of all the values. The caller can treat it as a single tuple, or it can assign the values to individual variables. Many standard Python libraries do this, including the os
module, which you'll learn about in the next chapter.
⁂
A set is an unordered “bag” of unique values. A single set can contain values of any immutable datatype. Once you have two sets, you can do standard set operations like union, intersection, and set difference.
First things first. Creating a set is easy.
>>> a_set = {1} ① >>> a_set {1} >>> type(a_set) ② <class 'set'> >>> a_set = {1, 2} ③ >>> a_set {1, 2}
{}
).
You can also create a set out of a list.
>>> a_list = ['a', 'b', 'mpilgrim', True, False, 42] >>> a_set = set(a_list) ① >>> a_set ② {'a', False, 'b', True, 'mpilgrim', 42} >>> a_list ③ ['a', 'b', 'mpilgrim', True, False, 42]
set()
function. (Pedants who know about how sets are implemented will point out that this is not really calling a function, but instantiating a class. I promise you will learn the difference later in this book. For now, just know that set()
acts like a function, and it returns a set.)
Don’t have any values yet? Not a problem. You can create an empty set.
>>> a_set = set() ① >>> a_set ② set() >>> type(a_set) ③ <class 'set'> >>> len(a_set) ④ 0 >>> not_sure = {} ⑤ >>> type(not_sure) <class 'dict'>
set()
with no arguments.
{}
, perhaps? That would denote an empty dictionary, not an empty set. You’ll learn about dictionaries later in this chapter.
There are two different ways to add values to an existing set: the add()
method, and the update()
method.
>>> a_set = {1, 2} >>> a_set.add(4) ① >>> a_set {1, 2, 4} >>> len(a_set) ② 3 >>> a_set.add(1) ③ >>> a_set {1, 2, 4} >>> len(a_set) ④ 3
add()
method takes a single argument, which can be any datatype, and adds the given value to the set.
>>> a_set = {1, 2, 3} >>> a_set {1, 2, 3} >>> a_set.update({2, 4, 6}) ① >>> a_set ② {1, 2, 3, 4, 6} >>> a_set.update({3, 6, 9}, {1, 2, 3, 5, 8, 13}) ③ >>> a_set {1, 2, 3, 4, 5, 6, 8, 9, 13} >>> a_set.update([10, 20, 30]) ④ >>> a_set {1, 2, 3, 4, 5, 6, 8, 9, 10, 13, 20, 30}
update()
method takes one argument, a set, and adds all its members to the original set. It’s as if you called the add()
method with each member of the set.
update()
method with any number of arguments. When called with two sets, the update()
method adds all the members of each set to the original set (dropping duplicates).
update()
method can take objects of a number of different datatypes, including lists. When called with a list, the update()
method adds all the items of the list to the original set.
There are three ways to remove individual values from a set. The first two, discard()
and remove()
, have one subtle difference.
>>> a_set = {1, 3, 6, 10, 15, 21, 28, 36, 45} >>> a_set {1, 3, 36, 6, 10, 45, 15, 21, 28} >>> a_set.discard(10) ① >>> a_set {1, 3, 36, 6, 45, 15, 21, 28} >>> a_set.discard(10) ② >>> a_set {1, 3, 36, 6, 45, 15, 21, 28} >>> a_set.remove(21) ③ >>> a_set {1, 3, 36, 6, 45, 15, 28} >>> a_set.remove(21) ④ Traceback (most recent call last): File "<stdin>", line 1, in <module> KeyError: 21
discard()
method takes a single value as an argument and removes that value from the set.
discard()
method with a value that doesn’t exist in the set, it does nothing. No error; it’s just a no-op.
remove()
method also takes a single value as an argument, and it also removes that value from the set.
remove()
method raises a KeyError
exception.
Like lists, sets have a pop()
method.
>>> a_set = {1, 3, 6, 10, 15, 21, 28, 36, 45} >>> a_set.pop() ① 1 >>> a_set.pop() 3 >>> a_set.pop() 36 >>> a_set {6, 10, 45, 15, 21, 28} >>> a_set.clear() ② >>> a_set set() >>> a_set.pop() ③ Traceback (most recent call last): File "<stdin>", line 1, in <module> KeyError: 'pop from an empty set'
pop()
method removes a single value from a set and returns the value. However, since sets are unordered, there is no “last” value in a set, so there is no way to control which value gets removed. It is completely arbitrary.
clear()
method removes all values from a set, leaving you with an empty set. This is equivalent to a_set = set()
, which would create a new empty set and overwrite the previous value of the a_set variable.
KeyError
exception.
Python’s set
type supports several common set operations.
>>> a_set = {2, 4, 5, 9, 12, 21, 30, 51, 76, 127, 195} >>> 30 in a_set ① True >>> 31 in a_set False >>> b_set = {1, 2, 3, 5, 6, 8, 9, 12, 15, 17, 18, 21} >>> a_set.union(b_set) ② {1, 2, 195, 4, 5, 6, 8, 12, 76, 15, 17, 18, 3, 21, 30, 51, 9, 127} >>> a_set.intersection(b_set) ③ {9, 2, 12, 5, 21} >>> a_set.difference(b_set) ④ {195, 4, 76, 51, 30, 127} >>> a_set.symmetric_difference(b_set) ⑤ {1, 3, 4, 6, 8, 76, 15, 17, 18, 195, 127, 30, 51}
in
operator. This works the same as lists.
union()
method returns a new set containing all the elements that are in either set.
intersection()
method returns a new set containing all the elements that are in both sets.
difference()
method returns a new set containing all the elements that are in a_set but not b_set.
symmetric_difference()
method returns a new set containing all the elements that are in exactly one of the sets.
Three of these methods are symmetric.
# continued from the previous example >>> b_set.symmetric_difference(a_set) ① {3, 1, 195, 4, 6, 8, 76, 15, 17, 18, 51, 30, 127} >>> b_set.symmetric_difference(a_set) == a_set.symmetric_difference(b_set) ② True >>> b_set.union(a_set) == a_set.union(b_set) ③ True >>> b_set.intersection(a_set) == a_set.intersection(b_set) ④ True >>> b_set.difference(a_set) == a_set.difference(b_set) ⑤ False
Finally, there are a few questions you can ask of sets.
>>> a_set = {1, 2, 3} >>> b_set = {1, 2, 3, 4} >>> a_set.issubset(b_set) ① True >>> b_set.issuperset(a_set) ② True >>> a_set.add(5) ③ >>> a_set.issubset(b_set) False >>> b_set.issuperset(a_set) False
False
.
You can use sets in a boolean context, such as an if
statement.
>>> def is_it_true(anything): ... if anything: ... print("yes, it's true") ... else: ... print("no, it's false") ... >>> is_it_true(set()) ① no, it's false >>> is_it_true({'a'}) ② yes, it's true >>> is_it_true({False}) ③ yes, it's true
⁂
A dictionary is an unordered set of key-value pairs. When you add a key to a dictionary, you must also add a value for that key. (You can always change the value later.) Python dictionaries are optimized for retrieving the value when you know the key, but not the other way around.
☞A dictionary in Python is like a hash in Perl 5. In Perl 5, variables that store hashes always start with a
%
character. In Python, variables can be named anything, and Python keeps track of the datatype internally.
Creating a dictionary is easy. The syntax is similar to sets, but instead of values, you have key-value pairs. Once you have a dictionary, you can look up values by their key.
>>> a_dict = {'server': 'db.diveintopython3.org', 'database': 'mysql'} ① >>> a_dict {'server': 'db.diveintopython3.org', 'database': 'mysql'} >>> a_dict['server'] ② 'db.diveintopython3.org' >>> a_dict['database'] ③ 'mysql' >>> a_dict['db.diveintopython3.org'] ④ Traceback (most recent call last): File "<stdin>", line 1, in <module> KeyError: 'db.diveintopython3.org'
'server'
is a key, and its associated value, referenced by a_dict['server']
, is 'db.diveintopython3.org'
.
'database'
is a key, and its associated value, referenced by a_dict['database']
, is 'mysql'
.
a_dict['server']
is 'db.diveintopython3.org'
, but a_dict['db.diveintopython3.org']
raises an exception, because 'db.diveintopython3.org'
is not a key.
Dictionaries do not have any predefined size limit. You can add new key-value pairs to a dictionary at any time, or you can modify the value of an existing key. Continuing from the previous example:
>>> a_dict {'server': 'db.diveintopython3.org', 'database': 'mysql'} >>> a_dict['database'] = 'blog' ① >>> a_dict {'server': 'db.diveintopython3.org', 'database': 'blog'} >>> a_dict['user'] = 'mark' ② >>> a_dict ③ {'server': 'db.diveintopython3.org', 'user': 'mark', 'database': 'blog'} >>> a_dict['user'] = 'dora' ④ >>> a_dict {'server': 'db.diveintopython3.org', 'user': 'dora', 'database': 'blog'} >>> a_dict['User'] = 'mark' ⑤ >>> a_dict {'User': 'mark', 'server': 'db.diveintopython3.org', 'user': 'dora', 'database': 'blog'}
'user'
, value 'mark'
) appears to be in the middle. In fact, it was just a coincidence that the items appeared to be in order in the first example; it is just as much a coincidence that they appear to be out of order now.
user
key back to "mark"? No! Look at the key closely — that’s a capital U in "User". Dictionary keys are case-sensitive, so this statement is creating a new key-value pair, not overwriting an existing one. It may look similar to you, but as far as Python is concerned, it’s completely different.
Dictionaries aren’t just for strings. Dictionary values can be any datatype, including integers, booleans, arbitrary objects, or even other dictionaries. And within a single dictionary, the values don’t all need to be the same type; you can mix and match as needed. Dictionary keys are more restricted, but they can be strings, integers, and a few other types. You can also mix and match key datatypes within a dictionary.
In fact, you’ve already seen a dictionary with non-string keys and values, in your first Python program.
SUFFIXES = {1000: ['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'],
1024: ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']}
Let's tear that apart in the interactive shell.
>>> SUFFIXES = {1000: ['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'], ... 1024: ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']} >>> len(SUFFIXES) ① 2 >>> 1000 in SUFFIXES ② True >>> SUFFIXES[1000] ③ ['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'] >>> SUFFIXES[1024] ④ ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'] >>> SUFFIXES[1000][3] ⑤ 'TB'
len()
function gives you the number of keys in a dictionary.
in
operator to test whether a specific key is defined in a dictionary.
1000
is a key in the SUFFIXES
dictionary; its value is a list of eight items (eight strings, to be precise).
1024
is a key in the SUFFIXES
dictionary; its value is also a list of eight items.
SUFFIXES[1000]
is a list, you can address individual items in the list by their 0-based index.
You can also use a dictionary in a boolean context, such as an if
statement.
>>> def is_it_true(anything): ... if anything: ... print("yes, it's true") ... else: ... print("no, it's false") ... >>> is_it_true({}) ① no, it's false >>> is_it_true({'a': 1}) ② yes, it's true
⁂
None
None
is a special constant in Python. It is a null value. None
is not the same as False
. None
is not 0. None
is not an empty string. Comparing None
to anything other than None
will always return False
.
None
is the only null value. It has its own datatype (NoneType
). You can assign None
to any variable, but you can not create other NoneType
objects. All variables whose value is None
are equal to each other.
>>> type(None) <class 'NoneType'> >>> None == False False >>> None == 0 False >>> None == '' False >>> None == None True >>> x = None >>> x == None True >>> y = None >>> x == y True
None
In A Boolean ContextIn a boolean context, None
is false and not None
is true.
>>> def is_it_true(anything): ... if anything: ... print("yes, it's true") ... else: ... print("no, it's false") ... >>> is_it_true(None) no, it's false >>> is_it_true(not None) yes, it's true
⁂
fractions
module
math
module
© 2001–11 Mark Pilgrim