1.8. Comencemos con los datos

Hemos dicho anteriormente que Python soporta el paradigma de programación orientado a objetos. Esto significa que Python considera que los datos son el punto focal del proceso de solución de problemas. En Python, así como en cualquier otro lenguaje de programación orientado a objetos, definimos una clase como una descripción de cómo lucen los datos (el estado) y lo que los datos pueden hacer (el comportamiento). Las clases son análogas a los tipos abstractos de datos porque un usuario de una clase sólo ve el estado y el comportamiento de un ítem de datos. Los ítems de datos se llaman objetos en el paradigma orientado a objetos. Un objeto es una instancia de una clase.

1.8.1. Tipos de datos atómicos incorporados

Comenzaremos nuestro repaso considerando los tipos de datos atómicos. Python tiene dos clases numéricas incorporadas principales que implementan los tipos de datos enteros y de punto flotante. Estas clases de Python se llaman int y float. Las operaciones aritméticas estándar, +, -, *, /, y ** (potenciación), pueden utilizarse con paréntesis para forzar que el orden de las operaciones se aleje de la precedencia normal del operador. Otras operaciones muy útiles son el operador de residuo (módulo), %, y la división entera, //. Tenga en cuenta que cuando se dividen dos enteros, el resultado es de punto flotante. El operador de división entera devuelve la porción entera del cociente truncando cualquier parte fraccionaria.

El tipo de datos booleano, implementado como la clase bool de Python, será muy útil para representar valores de verdad. Los posibles valores de estado para un objeto booleano son True y False con los operadores booleanos estándar, and, or y not.

>>> True
True
>>> False
False
>>> False or True
True
>>> not (False or True)
False
>>> True and True
True

Los objetos de datos booleanos también se utilizan como resultados para operadores de comparación tales como igualdad (==) y mayor que (\(>\)). Además, los operadores relacionales y los operadores lógicos pueden combinarse para formar preguntas lógicas complejas. La Tabla 1 muestra los operadores relacionales y lógicos con ejemplos mostrados en la sesión que sigue a continuación.

Tabla 1: Operadores relacionales y lógicos
Nombre de la operación Operador Explicación
menor que \(<\) Operador menor que
mayor que \(>\) Operador mayor que
menor que o igual \(<=\) Operador menor que o igual a
mayor que o igual \(>=\) Operador mayor que o igual a
igual \(==\) Operador de igualdad
no igual \(!=\) Operador de no igualdad
and lógica \(and\) Ambos operandos deben ser True para que el resultado sea True
or lógica \(or\) Al menos un operando debe ser True para que el resultado sea True
not lógica \(not\) Niega el valor de verdad. si es False lo vuelve True, si es True lo vuelve False

Los identificadores se utilizan en los lenguajes de programación como nombres. En Python, los identificadores comienzan con una letra o un guión bajo (_), son sensibles a mayúsculas y minúsculas, y pueden ser de cualquier longitud. Recuerde que siempre es una buena idea usar nombres que tengan significado para que su código de programa sea más fácil de leer y entender.

Una variable en Python se crea cuando se utiliza un nombre por primera vez en el lado izquierdo de una instrucción de asignación. Las instrucciones de asignación proporcionan una forma de asociar un nombre a un valor. La variable contendrá una referencia a una pieza de datos y no a los datos en sí. Considere la siguiente sesión:

>>> laSuma = 0
>>> laSuma
0
>>> laSuma = laSuma + 1
>>> laSuma
1
>>> laSuma = True
>>> laSuma
True

La instrucción de asignación laSuma = 0 crea una variable llamada laSuma y le permite contener la referencia al objeto de datos 0 (ver la Figura 3). En general, se evalúa el lado derecho de la instrucción de asignación y se asigna una referencia al objeto de datos resultante al nombre en el lado izquierdo. En este punto de nuestro ejemplo, el tipo de la variable es entero, ya que es el tipo de los datos a los que se refiere actualmente laSuma. Si el tipo de datos cambia (véase la Figura 4), como se muestra arriba con el valor booleano True, también cambia el tipo de la variable (laSuma es ahora de tipo booleano). La instrucción de asignación cambia la referencia que está siendo retenida por la variable. Ésta es una característica dinámica de Python. La misma variable puede referirse a muchos tipos diferentes de datos.

../_images/assignment1.png

Figura 3: Las variables contienen referencias a los objetos de datos

Figura 3: Las variables contienen referencias a los objetos de datos
../_images/assignment2.png

Figura 4: La asignación cambia la referencia

Figura 4: La asignación cambia la referencia

1.8.2. Tipos de datos de colecciones incorporados

Además de las clases numéricas y booleanas, Python tiene una serie de clases de colecciones muy potentes. Las listas, las cadenas y las tuplas son colecciones ordenadas muy similares en la estructura general pero que tienen diferencias específicas que deben ser entendidas para que sean usadas correctamente. Los conjuntos y los diccionarios son colecciones no ordenadas.

Una lista es una colección ordenada de cero o más referencias a objetos de datos de Python. Las listas se escriben como valores delimitados por comas encerrados entre corchetes. La lista vacía es simplemente [ ]. Las listas son heterogéneas, lo que significa que los objetos de datos no necesitan ser todos de la misma clase y la colección se puede asignar a una variable como se muestra a continuación. El siguiente fragmento muestra una variedad de objetos de datos de Python en una lista.

>>> [1,3,True,6.5]
[1, 3, True, 6.5]
>>> miLista = [1,3,True,6.5]
>>> miLista
[1, 3, True, 6.5]

Tenga en cuenta que cuando Python evalúa una lista, la misma lista es devuelta. Sin embargo, con el fin de recordar la lista para un procesamiento posterior, su referencia debe asignarse a una variable.

Dado que las listas se consideran ordenadas secuencialmente, admiten varias operaciones que se pueden aplicar a cualquier secuencia de Python. La Tabla 2 compendia estas operaciones y la sesión subsiguiente da ejemplos de su uso.

Tabla 2: Operaciones sobre cualquier secuencia en Python
Nombre de la operación Operador Explicación
indización [ ] Acceso a un elemento de la secuencia
concatenación + Combina secuencias
repetición * Concatena un número repetido de veces
membresía in Pregunta si un ítem está en una secuencia
longitud len Pregunta el número de ítems en la secuencia
partición [ : ] Extrae una parte de una secuencia

Note que los índices para las listas (secuencias) comienzan contando en 0. La operación de partición, miLista[1:3], devuelve una lista de ítems que empieza con el ítem indizado por 1 y que va hasta el ítem indizado por 3 pero sin incluirlo.

A veces, usted querrá inicializar una lista. Esto se puede lograr rápidamente usando la repetición. Por ejemplo,

>>> miLista = [0] * 6
>>> miLista
[0, 0, 0, 0, 0, 0]

Un aspecto muy importante relacionado con el operador de repetición es que el resultado es una repetición de referencias a los objetos de datos en la secuencia. Esto puede verse mejor considerando la siguiente sesión:

La variable A contiene una colección de tres referencias a la lista original llamada miLista. Tenga en cuenta que un cambio a un elemento de miLista se refleja en las tres apariciones en A.

Las listas admiten varios métodos que se utilizarán para crear estructuras de datos. La Tabla 3 proporciona un resumen. Después se muestran ejemplos de su uso.

Tabla 3: Métodos suministrados por las listas en Python
Nombre del método Uso Explicación
append unaLista.append(item) Agrega un nuevo ítem al final de una lista
insert unaLista.insert(i,item) Inserta un ítem en la i-ésima posición en una lista
pop unaLista.pop() Elimina y devuelve el último ítem de una lista
pop unaLista.pop(i) Elimina y devuelve el i-ésimo ítem en una lista
sort unaLista.sort() Modifica una lista para que quede ordenada
reverse unaLista.reverse() Modifica una lista para que quede en orden inverso
del del unaLista[i] Borra el ítem en la i-ésima posición
index unaLista.index(item) Devuelve el índice de la primera aparición de item
count unaLista.count(item) Devuelve el número de apariciones de item
remove unaLista.remove(item) Elimina la primera aparición de item

Usted puede ver que algunos de los métodos, como pop, devuelven un valor y también modifican la lista. Otros, como reverse, simplemente modifican la lista sin devolver valor. pop actuará por defecto sobre el final de la lista, pero también puede eliminar y devolver un ítem específico. El rango de índices que comienza a partir de 0 se utiliza de nuevo para estos métodos. Usted también debe fijarse en la notación familiar de “punto” para pedir a un objeto que invoque un método. miLista.append (False) se puede leer como “pedir al objeto miLista que ejecute su método append y le envíe el valor False”. Incluso objetos de datos simples tales como los enteros pueden invocar métodos de esta manera.

>>> (54).__add__(21)
75
>>>

En este fragmento pedimos al objeto entero 54 que ejecute su método add (llamado __add__ en Python) y le pasemos 21 como el valor a sumar. El resultado es la suma, 75. Por supuesto, solemos escribir esto como 54 + 21. Diremos mucho más sobre estos métodos más adelante en esta sección.

Una función común de Python que se discute a menudo junto con las listas es la función range. range produce un objeto range que representa una secuencia de valores. Mediante el uso de la función list, es posible ver el valor del objeto range como una lista. Esto se ilustra a continuación.

>>> range(10)
range(0, 10)
>>> list(range(10))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> range(5,10)
range(5, 10)
>>> list(range(5,10))
[5, 6, 7, 8, 9]
>>> list(range(5,10,2))
[5, 7, 9]
>>> list(range(10,1,-1))
[10, 9, 8, 7, 6, 5, 4, 3, 2]
>>>

El objeto range representa una secuencia de enteros. Por defecto, iniciará con 0. Si se proporcionan más parámetros, iniciará y finalizará en determinados puntos e incluso puede omitir ítems. En nuestro primer ejemplo, range(10), la secuencia comienza con 0 y va hasta pero no incluye a 10. En nuestro segundo ejemplo, range(5,10) comienza en 5 y va hasta pero no incluye a 10. range (5,10,2) se comporta de manera similar, pero omite valores de dos en dos (nuevamente, 10 no está incluido).

Las cadenas son colecciones secuenciales de cero o más letras, números y otros símbolos. Llamamos a estas letras, números y otros símbolos caracteres. Los valores de las cadenas literales se diferencian de los identificadores mediante el uso de comillas (simples o dobles).

>>> "David"
'David'
>>> miNombre = "David"
>>> miNombre[3]
'i'
>>> miNombre*2
'DavidDavid'
>>> len(miNombre)
5
>>>

Dado que las cadenas son secuencias, todas las operaciones para secuencias descritas anteriormente funcionan como se esperaría. Además, las cadenas tienen una serie de métodos, algunos de los cuales se muestran en la Tabla 4. Por ejemplo,

>>> miNombre
'David'
>>> miNombre.upper()
'DAVID'
>>> miNombre.center(10)
'  David   '
>>> miNombre.find('v')
2
>>> miNombre.split('v')
['Da', 'id']

De estos métodos, split será muy útil para el procesamiento de datos. split tomará una cadena y devolverá una lista de cadenas usando el caracter especificado en el argumento como punto de división. En el ejemplo, v es el punto de división. Si no se especifica ninguna división, el método split busca caracteres de espacios en blanco como tabulación, nueva línea y espacio.

Tabla 4: Métodos suministrados por las cadenas en Python
Nombre del método Uso Explicación
center unaCadena.center(w) Devuelve una cadena centrada en un campo de tamaño w
count unaCadena.count(item) Devuelve el número de apariciones de item en la cadena
ljust unaCadena.ljust(w) Devuelve una cadena justificada a la izquierda en un campo de tamaño w
lower unaCadena.lower() Devuelve una cadena en minúsculas
rjust unaCadena.rjust(w) Devuelve una cadena justificada a la derecha en un campo de tamaño w
find unaCadena.find(item) Devuelve el índice de la primera aparición de item
split unaCadena.split(cardiv) Divide una cadena en subcadenas en cardiv

Una diferencia importante entre las listas y las cadenas es que las listas se pueden modificar mientras que las secuencias no pueden ser modificadas. Esto se conoce como mutabilidad. Las listas son mutables; Las cadenas son inmutables. Por ejemplo, usted puede cambiar un ítem de una lista mediante la indización y la asignación. Con una cadena tal cambio no está permitido.

>>> miLista
[1, 3, True, 6.5]
>>> miLista[0]=2**10
>>> miLista
[1024, 3, True, 6.5]
>>>
>>> miNombre
'David'
>>> miNombre[0]='X'

Traceback (most recent call last):
  File "<pyshell#84>", line 1, in -toplevel-
    miNombre[0]='X'
TypeError: object doesn't support item assignment
>>>

Las tuplas son muy similares a las listas en que son secuencias heterogéneas de datos. La diferencia es que una tupla es inmutable, como una cadena. No se puede cambiar una tupla. Las tuplas se escriben como valores delimitados por comas encerrados entre paréntesis. Como secuencias, pueden utilizar cualquier operación descrita anteriormente. Por ejemplo,

>>> miTupla = (2,True,4.96)
>>> miTupla
(2, True, 4.96)
>>> len(miTupla)
3
>>> miTupla[0]
2
>>> miTupla * 3
(2, True, 4.96, 2, True, 4.96, 2, True, 4.96)
>>> miTupla[0:2]
(2, True)
>>>

Sin embargo, si usted intenta cambiar un ítem en una tupla, obtendrá un error. Note que el mensaje de error proporciona la ubicación y el motivo del problema.

>>> miTupla[1]=False

Traceback (most recent call last):
  File "<pyshell#137>", line 1, in -toplevel-
    miTupla[1]=False
TypeError: object doesn't support item assignment
>>>

Un conjunto es una colección no ordenada de cero o más objetos de datos de Python inmutables. Los conjuntos no permiten duplicaciones y se escriben como valores delimitados por comas encerrados entre llaves. El conjunto vacío está representado por set(). Los conjuntos son heterogéneos y la colección se puede asignar a una variable como se muestra a continuación.

>>> {3,6,"gato",4.5,False}
{False, 4.5, 3, 6, 'gato'}
>>> miConjunto = {3,6,"gato",4.5,False}
>>> miConjunto
{False, 4.5, 3, 6, 'gato'}
>>>

Aunque los conjuntos no se consideran secuenciales, sí soportan algunas de las operaciones conocidas qe fueron presentadas anteriormente. La Tabla 5 compendia estas operaciones y la siguiente sesión da ejemplos de su uso.

Tabla 5: Operaciones sobre un conjunto en Python
Nombre de la operación Operador Explicación
membresía in Membresía del conjunto
longitud len Devuelve la cardinalidad del conjunto
| unConjunto | otroConjunto Devuelve un nuevo conjunto con todos los elementos de ambos conjuntos
& unConjunto & otroConjunto Devuelve un nuevo conjunto con sólo los elementos comunes a ambos conjuntos
- unConjunto - otroConjunto Devuelve un nuevo conjunto con todos los ítems del primer conjunto que no están en el segundo
<= unConjunto <= otroConjunto Pregunta si todos los elementos del primer conjunto están en el segundo
>>> miConjunto
{False, 4.5, 3, 6, 'gato'}
>>> len(miConjunto)
5
>>> False in miConjunto
True
>>> "perro" in miConjunto
False
>>>

Los conjuntos soportan una serie de métodos que deben ser familiares para aquellos que han trabajado con ellos en el contexto de las matemáticas. La Tabla 6 proporciona un resumen de ellos. Siguen ejemplos de su uso. Tenga en cuenta que union, intersection, issubset y difference tienen operadores que también se pueden utilizar.

Tabla 6: Métodos proporcionados por los conjuntos en Python
Nombre del método Uso Explicación
union unConjunto.union(otroConjunto) Devuelve un nuevo conjunto con todos los elementos de ambos conjuntos
intersection unConjunto.intersection(otroConjunto) Devuelve un nuevo conjunto con sólo los elementos comunes a ambos conjuntos
difference unConjunto.difference(otroConjunto) Devuelve un nuevo conjunto con todos los elementos del primer conjunto que no están en el segundo
issubset unConjunto.issubset(otroConjunto) Pregunta si todos los elementos de un conjunto están en el otro
add unConjunto.add(item) Añade item al conjunto
remove unConjunto.remove(item) Elimina item del conjunto
pop unConjunto.pop() Elimina un elemento arbitrario del conjunto
clear unConjunto.clear() Elimina todos los elementos del conjunto
>>> miConjunto
{False, 4.5, 3, 6, 'gato'}
>>> tuConjunto = {99,3,100}
>>> miConjunto.union(tuConjunto)
{False, 4.5, 3, 100, 6, 'gato', 99}
>>> miConjunto | tuConjunto
{False, 4.5, 3, 100, 6, 'gato', 99}
>>> miConjunto.intersection(tuConjunto)
{3}
>>> miConjunto & tuConjunto
{3}
>>> miConjunto.difference(tuConjunto)
{False, 4.5, 6, 'gato'}
>>> miConjunto - tuConjunto
{False, 4.5, 6, 'gato'}
>>> {3,100}.issubset(tuConjunto)
True
>>> {3,100}<=tuConjunto
True
>>> miConjunto.add("casa")
>>> miConjunto
{False, 4.5, 3, 6, 'casa', 'gato'}
>>> miConjunto.remove(4.5)
>>> miConjunto
{False, 3, 6, 'casa', 'gato'}
>>> miConjunto.pop()
False
>>> miConjunto
{3, 6, 'casa', 'gato'}
>>> miConjunto.clear()
>>> miConjunto
set()
>>>

Nuestra colección final de Python es una estructura no ordenada llamada diccionario. Los diccionarios son colecciones de parejas de ítems asociadas en las que cada pareja consiste en una clave y un valor. Esta pareja clave-valor suele escribirse como clave:valor. Los diccionarios se escriben como parejas clave:valor delimitadas por comas encerradas entre llaves. Por ejemplo,

>>> capitales = {'Iowa':'DesMoines','Wisconsin':'Madison'}
>>> capitales
{'Wisconsin': 'Madison', 'Iowa': 'DesMoines'}
>>>

Podemos manipular un diccionario accediendo a un valor a través de su clave o añadiendo otra pareja clave-valor. La sintaxis para el acceso se parece mucho a un acceso de secuencia, excepto que en lugar de utilizar el índice del ítem utilizamos la clave. Agregar un valor nuevo es similar.

Es importante tener en cuenta que el diccionario se mantiene sin un orden particular con respecto a las claves. La primera pareja añadida ('Utah': 'SaltLakeCity') fue ubicada como primera en el diccionario y la segunda pareja añadida ('California': 'Sacramento') fue ubicada en último lugar. La ubicación de una clave depende de la idea de “transformación de claves” (hashing por su nombre en inglés), que se explicará con más detalle en el Capítulo 4. También mostramos la función len que desempeña el mismo papel que con las colecciones anteriores.

Los diccionarios tienen métodos y operadores. La Tabla 7 y la Tabla 8 los describen, y la sesión los muestra en acción. Los métodos keys, values e items devuelven objetos que contienen los valores de interés. Se puede usar la función list para convertirlos en listas. Usted también verá que hay dos variaciones en el método get. Si la clave no está presente en el diccionario, get devolverá None. Sin embargo, un segundo parámetro opcional puede especificar un valor devuelto.

Tabla 7: Operadores proporcionados por los diccionarios en Python
Operador Uso Explicación
[] miDicc[k] Devuelve el valor asociado con k, de lo contrario es un error
in clave in unDicc Devuelve True si clave está en el diccionario, False de lo contrario
del del unDicc[clave] Elimina la entrada del diccionario
>>> extenTel={'david':1410,'brad':1137}
>>> extenTel
{'brad': 1137, 'david': 1410}
>>> extenTel.keys()
dict_keys(['brad', 'david'])
>>> list(extenTel.keys())
['brad', 'david']
>>> extenTel.values()
dict_values([1137, 1410])
>>> list(extenTel.values())
[1137, 1410]
>>> extenTel.items()
dict_items([('brad', 1137), ('david', 1410)])
>>> list(extenTel.items())
[('brad', 1137), ('david', 1410)]
>>> extenTel.get("kent")
>>> extenTel.get("kent","NO HAY ENTRADA")
'NO HAY ENTRADA'
>>>
Tabla 8: Métodos proporcionados por los diccionarios en Python
Nombre del método Uso Explicación
keys unDicc.keys() Devuelve las claves del diccionario en un objeto dict_keys
values unDicc.values() Devuelve los valores del diccionario en un objeto dict_values
items unDicc.items() Devuelve las parejas clave-valor en un objeto dict_items
get unDicc.get(k) Devuelve el valor asociado con k, None de lo contrario
get unDicc.get(k,alt) Devuelve el valor asociado con k, alt en caso contrario

Note

Este espacio de trabajo se proporciona para su comodidad. Usted puede usar esta ventana de activecode para probar lo que quiera.

Next Section - 1.9. Entrada y salida