Tipos de Datos en Python
- Lenguajes de tipado estático como C o Java requieren que cada vriable sea declarada explicitamente
- Python en un lenguaje de tipado dinámico y no requiere ésta especificación Por ejemplo en C especificamos una operación como sigue:
/* codigo en C */
int result = 0;
for(int i=0; i<100; i++){
result += i;
}
En Python la operación equivalente puede escribirse de la siguiente forma:
# codigo en Python
result = 0
for i in range(100):
result += i
La diferencia principal es
- en C el tipo de cada variable debe especificarse explicitamente
- en Python el tipo de cada variable es inferido dinamicamente
De este modo, en Python podemos asignar cualquier tipo de datos a cualquier variables:
# codigo Python
x = 4
x = "four"
El equivalente en C sería como sigue, sin embargo, tendría errores de compilación o consecuencias inesperadas:
/* codigo C */
int x = 4;
x = "four"; // ERROR
- Las variables en Python son más que sólo su valor
- Contienen información extra sobre el tipo de valor, es decir el tipo de dato que representan.
Enteros en Python¶
- La implementacion standard de Python está escrita en C.
- Si definimos un entero en Python,
x = 10000
,x
es un apuntador a una estructura de C:
struct _longobject {
long ob_refcnt;
PyTypeObject *ob_type;
size_t ob_size;
long ob_digit[1];
};
Un entero en Python contiene cuatro partes:
ob_refcnt
, un contador que ayuda en la asignación y liberación de memoriaob_type
, codifica el tipo de variableob_size
, especifica el tamañoob_digit
, contiene el valor asignado que representa la variable.
Esto causa un pequeño overhead cuando se crea un entero en Python en comparación con C, como se ilustra a continuación:
Listas en Python¶
Una lista es una estructura de datos que permite colectar objetos. Creamos una lista de enteros de la siguiente forma:
L = list(range(10))
L
type(L[0])
O una lista de caracteres de texto:
L2 = [str(c) for c in L]
L2
type(L2[0])
Gracias al tipado dinámico podemos crear listas heterogéneas:
L3 = [True, "2", 3.0, 4]
[type(item) for item in L3]
- Esta felixibilidad tiene un costo pues cada elemento en la lista contiene es una referencia a una estructura que define el objeto de Python.
- En el caso especial que todas las entradas son del mismo tipo habrá información redundante: - Sería mas eficiente usar un arreglo de tipo fijo
- La diferencia entre listas dinámicas y de tipo fijo (como NumPy) se ilustra en la siguiente figura:
- El arreglo contiene un apuntador único a un bloque contiguo de datos
- La lista contiene un apuntador a un bloque de apuntadores, cada uno apuntando a un objeto de Python (como el objeto entero que vimos antes)
- La lista puede tener objetos y datos de cualquier tipo
- El arreglo fijo no puede hacerlo, pero es mas eficiente para guardar y manipular los datos
Arreglos de Tipo Fijo en Python¶
- En Python hay diferentes opciones para guardar datos en buffers de tipo fijo
- El modulo interno
array
(disponible a partir de Python 3.3) sirve para crear arreglos densos de tipo uniforme:
import array
L = list(range(10))
A = array.array('i', L)
A
- Aquí
'i'
indica que las entradas son enteros. - El objeto
ndarray
de la libreria NumPy es mucho mas útil ya que implementa operaciones sobre los datos contenidos. - Antes de explorar estas operaciones, veamos diversas maneras de crear arreglos de NumPy
- Comenzamos con la manera standard de importar NumPy, usando el alias
np
:
import numpy as np
Crear Arreglos a partir de Listas de Python¶
Podemos usar np.array
para crear arreglos a partir de listas:
# integer array:
np.array([1, 4, 2, 5, 3])
- A diferencia de las lista en Python, NumPy está restringif a arreglos que contienen el mismo tipo de datos
- Si los tipos no coinciden NumPy trata de ajustar (upcast, emitir) si es posible
- En el siguiente ejemplo, los enteros se emiten a punto flotante:
np.array([3.14, 4, 2, 3])
- Podemos indicar el tipo de datos del arreglo explicitamente usando la palabra
dtype
:
np.array([1, 2, 3, 4], dtype='float32')
- A diferencia de las listas, los arreglos de NumPy pueden ser explicitamente multi-dimensionales
- A continuación, una forma de inicializar un arreglo multidimensional usando una lista de listas:
# nested lists result in multi-dimensional arrays
np.array([range(i, i + 3) for i in [2, 4, 6]])
- Las listas interiores se toman como renglones del arreglo bidimensional resultante
Creando Arreglos¶
- Para arreglos grandes, es mas eficiente crearlos usando rutinas implementadas en NumPy:
# Crea arreglo de enteros de longitud-10 lleno de ceros
np.zeros(10, dtype=int)
# Crea arreglo con puntos flotantes de dimensiones 3x5 (3 renglones, 5 columnas) lleno de unos
np.ones((3, 5), dtype=float)
# Crea arreglo de 3x5 array lleno de 3.14
np.full((3, 5), 3.14)
# Crea arreglo lleno con una secuencia lineal de numeros
# Empieza en 0, acaba en 20, en pasos de 2
# (similar a la funcion interna range())
np.arange(0, 20, 2)
# Crea array de cinco valores igualmente espaciados entre 0 y 1
np.linspace(0, 1, 5)
# Crea un arreglo de 3x3 con valores aleatorios
# distribuidos de manera uniforma entre 0 y 1
np.random.random((3, 3))
# Crea un arreglo de 3x3 con valores aleatorios
# distribuidos de manera normal con media 0 y desviacion estandard 1
np.random.normal(0, 1, (3, 3))
# Crea array de 3x3 de numeros enterros aleatorios tomados del intervalo [0, 10)
np.random.randint(0, 10, (3, 3))
# Crea matrix identidad de 3x3 (arreglo cuyas entradas son todas cero excepto las diagonales)
np.eye(3)
# Crea un array de tres enteros sin valores especificos
# Los valores se toman de lo que exista en esa localizacion de la memoria
np.empty(3)
Tipos de Datos Standard de NumPy¶
- Los arrays de NumPy contienen valores de un solo tipo, veamos cuales pueden ser
- NumPy está implementado en C, de modo que los tipos son similares a los usados en C, Fortran, y otros lenguajes relacionados
- La siguiente tabla enlista los tipos de datos standard de NumPy
- Cuando construyen un array se puede especificar el tipo usando texto:
np.zeros(10, dtype='int16')
- O usando el objeto de NumPy asociado:
np.zeros(10, dtype=np.int16)
Data type | Description |
---|---|
bool_ |
Boolean (True or False) stored as a byte |
int_ |
Default integer type (same as C long ; normally either int64 or int32 ) |
intc |
Identical to C int (normally int32 or int64 ) |
intp |
Integer used for indexing (same as C ssize_t ; normally either int32 or int64 ) |
int8 |
Byte (-128 to 127) |
int16 |
Integer (-32768 to 32767) |
int32 |
Integer (-2147483648 to 2147483647) |
int64 |
Integer (-9223372036854775808 to 9223372036854775807) |
uint8 |
Unsigned integer (0 to 255) |
uint16 |
Unsigned integer (0 to 65535) |
uint32 |
Unsigned integer (0 to 4294967295) |
uint64 |
Unsigned integer (0 to 18446744073709551615) |
float_ |
Shorthand for float64 . |
float16 |
Half precision float: sign bit, 5 bits exponent, 10 bits mantissa |
float32 |
Single precision float: sign bit, 8 bits exponent, 23 bits mantissa |
float64 |
Double precision float: sign bit, 11 bits exponent, 52 bits mantissa |
complex_ |
Shorthand for complex128 . |
complex64 |
Complex number, represented by two 32-bit floats |
complex128 |
Complex number, represented by two 64-bit floats |
- Existen tipos mas avanzados; para mas información se refiere a la documentacion de NumPy.