Tipo Inteiro
Inteiro
O tipo usado para armazenar os números inteiros em Python é representado pela
classe int
. Em Python, nós não precisamos declarar qual o tipo de dado a ser
usado, pois o Python faz a inferência de tipos dinamicamente. O interpretador
primeiro verifica como o valor se parece e então decide por conta própria qual
a classe a ser utilizada. Abaixo, exemplos de uso de int
:
# a idade de uma pessoa
idade = 25
# o código de um produto
codigo_produto = 4587
# quantidade de itens
quantidade = 3
Em qualquer um dos casos acima, o Python irá armazenar como int
, e você pode
usar a função type
para verificar:
>>> type(idade)
int
Você até pode, se desejar, forçar o tipo de dado explicitamente, mas isso é considerado redundante:
idade = int(25) # isso funciona, mas é redundante
idade
é um identificador que faz referência ao valor 25 e nós podemos fazer
uma variedade de operações com este valor. Essas operações fazem parte do que
chamamos Protocolo do objeto, e quem define os protocolos que o objeto
implementa é a classe int
.
Você pode, no seu terminal, verificar todos os protocolos que o int
implementa.
Verificando quais comportamentos estão no protocolo de um tipo de dado. Verificando quais comportamentos estão no protocolo de um tipo de dado.
>>> dir(int)
# atributos especiais da classse int
['__abs__',
'__add__',
'__and__',
'__bool__',
'__ceil__',
'__class__',
'__delattr__',
'__dir__',
'__divmod__',
'__doc__',
'__eq__',
'__float__',
'__floor__',
'__floordiv__',
'__format__',
'__ge__',
'__getattribute__',
'__getnewargs__',
'__gt__',
'__hash__',
'__index__',
'__init__',
'__init_subclass__',
'__int__',
'__invert__',
'__le__',
'__lshift__',
'__lt__',
'__mod__',
'__mul__',
'__ne__',
'__neg__',
'__new__',
'__or__',
'__pos__',
'__pow__',
'__radd__',
'__rand__',
'__rdivmod__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__rfloordiv__',
'__rlshift__',
'__rmod__',
'__rmul__',
'__ror__',
'__round__',
'__rpow__',
'__rrshift__',
'__rshift__',
'__rsub__',
'__rtruediv__',
'__rxor__',
'__setattr__',
'__sizeof__',
'__str__',
'__sub__',
'__subclasshook__',
'__truediv__',
'__trunc__',
'__xor__',
# daqui para baixo estão atributos públicos que podemos usar diretamente
'as_integer_ratio',
'bit_count',
'bit_length',
'conjugate',
'denominator',
'from_bytes',
'imag',
'numerator',
'real',
'to_bytes']
A lista acima exibe os nomes de todos os atributos dos objetos armazenados com
a classe int
. Tudo o que começa com __
e termina com __
são chamados de
métodos
dunder e são atributos especiais do modelo de dados do Python. Não precisamos
usar esses atributos diretamente em nosso código (apesar de às vezes eles serem
úteis). Normalmente, utilizamos abstrações que por baixo dos panos farão a
chamada para esses métodos.
Neste momento, não vamos falar de todos eles, pois são muitos, e a ideia é que
aos poucos você vá entendendo conforme utiliza. Mas vamos explorar um exemplo
simples e que provavelmente usaremos sempre.
Protocolo Addible
Um dos métodos ali na lista retornada pelo dir(int)
é chamado __add__
(
Dunder Add). Add em português significa adicionar e todo objeto em Python
que possui este método __add__
nós chamamos de um objeto Addible. Isso
significa que com este objeto podemos efetuar operações de adição, ou seja,
podemos somar um número a outro.
Exemplo:
preco = 10
imposto = 2
total = preco + imposto
No exemplo acima, fizemos uma operação de soma utilizando 2 objetos
inteiros preco
e imposto
, e para efetuar a operação usamos o operador +
,
que é exatamente o que aprendemos nas aulas de matemática básica na escola.
Acontece que por debaixo dos panos, o Python ao
interpretar total = preco + imposto
vai, na verdade, efetuar outra operação,
ele vai fazer:
total = preco.__add__(imposto)
O operador +
é um símbolo que faz o Python invocar o método __add__
no
objeto que está do lado esquerdo de uma expressão.
IMPORTANTE: No dia a dia, nós usamos apenas os operadores da forma
abstraída. Por exemplo: 1 + 1
, 10 - 8
, 5 * 4
, etc. Porém, é importante
você saber como isso é implementado pelo Python, pois através de uma lista de
atributos você conseguirá determinar o que aquele objeto suporta de
operações. Todos os outros comportamentos que esperamos de um número inteiro
também estarão implementados naquela lista, alguns exemplos:
- A operação
preco - desconto
internamente épreco.__sub__(desconto)
. preco * quantidade
épreco.__mul__(quantidade)
.preco / parcelas
épreco.__div__(parcelas)
.
Essas são as 4 operações matemáticas básicas, mas para todos os outros
operadores como potenciação **
-> __pow__
, módulo %
-> __mod__
, terá
sempre um desses métodos dunder especiais.
E não apenas para operações matemáticas, essa lógica vai seguir para qualquer
outra expressão do Python, será muito comum nós fazermos comparações como
fizemos no nosso script hello.py
:
if current_language == "pt_BR":
msg = "Hello, World!"
A parte current_language == "pt_BR"
irá invocar o protocolo Comparable
que
faz com que o objeto possa ser comparado com outro e o método Dunder que
implementa essa funcionalidade é o __eq__
. Pode testar com:
>>> idade = 25
# Comparando por igualdade
>>> idade == 25
True
# O mesmo resultado
>>> idade.__eq__(25)
True
IMPORTANTE: Lembre-se que não usamos o .__eq__
diretamente, quem faz isso
para nós é o interpretador quando ele encontra o sinal de ==
. Teremos um
método dunder similar ao __eq__
no objeto para todos os outros operadores de
comparação, como por
exemplo >
-> __gt__
, <
-> __lt__
, >=
-> __ge__
, <=
-> __le__
e
assim por diante.
Esta mesma lógica vai ser usada para todos os outros tipos de dados em Python.