CAPÍTULO 2. Elementos del lenguaje
2.1. Estructura léxica
2.3.1.2. Listas
Las listas son secuencias de elementos ordenados que además tienen la característica de ser mutables. Cada elemento puede ser de cualquier tipo y la sintaxis para crearlas es bastante simple.
Otra alternativa para crear listas es a través de la función predefinida list() que toma como argumento una secuencia y devuelve una lista con cada elemento de esa secuencia. En caso de no recibir argumento devuelve una lista vacía.
El código anterior crea una lista a partir de la cadena “python”. Observe el lector como se imprime cada elemento de la lista resultante y como estos elementos coinciden con los caracteres del texto de la cadena.
2.3.1.3 Tuplas
Una tupla es una secuencia ordenada de elementos que, a diferencia de la lista, tiene la característica de ser inmutable y, por ende, las operaciones de modificación que se realizan sobre esta resultan en una nueva tupla, la original no sufre cambios. Al igual que sucede con las listas y como resulta lógico suponer considerando la naturaleza de Python, los elementos de una tupla pueden ser de cualquier tipo. La sintaxis general para crear una tupla es la siguiente:
(a1, a2,…, an)
Donde a1, a2,…, an son los elementos. En el siguiente código se pueden apreciar varias tuplas creadas en Python.
Para crear una tupla de un solo elemento se escribe una coma al final del elemento.
La función predefinida tuple() permite crear tuplas de manera análoga a la función list(), analizada en la sección anterior.
2.3.2 Diccionarios
Un diccionario es una correspondencia (del inglés mapping) que se establece en un multiconjunto de elementos de cardinalidad n. Este multiconjunto de elementos se encuentra particionado en dos multiconjuntos de igual cardinalidad (n/2), el conjunto de las llaves y el multiconjunto de valores. Entre estos conjuntos se establece una función inyectiva de manera tal que a cada llave le corresponde un elemento y un elemento puede estar asociado a varias llaves. El lector puede suponer entonces que un diccionario esté constituido por elementos de la forma llave-valor y que la manera en la que se accede a un elemento es mediante su llave. Los diccionarios, que son el único tipo de dato mapping que de manera predefinida ofrece Python, carecen de orden y son mutables. Las llaves al igual que los valores pueden ser objetos de cualquier tipo. La sintaxis genérica para definir un diccionario es la siguiente:
{llave_1: valor_1, llave_2: valor_2,…, llave_n: valor_n}
Considere el próximo ejemplo que ilustra en concreto la creación de un diccionario en Python.
La función dict() permite crear un diccionario a partir de una lista de listas que debe suministrarse como argumento. Cada lista debe contener dos elementos que representen los pares llave, y el valor.
Si no se suministra ningún argumento entonces la función dict() devuelve un diccionario vacío. En caso de que una llave se repita en la definición de un diccionario entonces el par que resulta será la llave duplicada junto a su último valor asociado tal y como se aprecia en el ejemplo a continuación:
Tenga en cuenta el lector que un diccionario no puede tener llaves duplicadas, en caso de tenerlas se crearía una clara ambigüedad puesto que una misma llave estaría asociada a dos valores posiblemente distintos y sería imposible recuperar con total certeza alguno de esos valores, la propiedad inyectiva se perdería dado que pudiera suceder que dicc[x] = dicc[y].
2.3.3 Numéricos
Python cuenta con tres objetos numéricos de manera predefinida, estos son: los objetos que representan números enteros, los que representan números complejos y aquellos que manejan números de punto flotante. Todos poseen la característica de ser inmutables de modo que una operación que se realice sobre ellos resulta en un nuevo objeto numérico.
Los objetos de tipo entero pueden tener diferentes representaciones según el literal con el que hayan sido definidos.
Estas representaciones pueden ser números decimales, hexadecimales u octales. Para indicar un número hexadecimal el literal debe aparecer antecedido del prefijo 0x y en caso de ser un octal debe aparecer prefijado por 0o precisamente como se observa en el ejemplo anterior. En Python 3.1 todos los enteros han sido implementados como enteros long.
Los objetos de punto flotante representan números reales basados en el sistema de punto flotante. Pueden aparecer acompañados de un símbolo E o e seguido del símbolo + y de un número llamado exponente para indicar que se desplaza a la derecha el punto del número (mantisa) que antecede a E tantas veces como indique el exponente; de manera análoga sucede con el símbolo (-) solo que en este caso el desplazamiento es a la izquierda, pues se está negando. Considere el siguiente código:
Para comprender en qué consisten los números de punto flotante con exponente positivo o negativo observe el resultado que se obtiene al imprimir f4 y f5.
Como puede comprobar el lector, f4 es equivalente al número 1, esto es porque .001E+3 equivale a (0.001)*10^3 = 1. En el segundo caso como el exponente es negativo equivale a (0.001)*10^ (-3) = 0.000001 que también puede representarse como 1E-6 = 10^ (-6). Los números de punto flotante en Python encuentran su correspondencia en los tipos double de C considerando rango y precisión.
Finalemente los números complejos se componen de dos valores de punto flotante, uno asociado a la parte imaginaria y otro a la parte real, accesibles estos valores por medio de propiedades de solo lectura imag y real del objeto complex que corresponde a un número complejo. Aunque en la literatura la parte imaginaria de los números complejos suele indicarse con la letra i la elección de Python ha sido utilizar la letra j. El siguiente código ilustra números complejos creados en Python.
Para imprimir la parte real e imaginaria de b se puede proceder de la siguiente forma:
La función __str__() con la que cuentan todos los objetos en Python devuelve su representación como cadena, necesaria en este caso para imprimir los valores de punto flotante que corresponden a las propiedades real e imag.
En las siguientes secciones se examinarán las operaciones que pueden realizarse tanto con secuencias como con objetos numéricos.
2.3.4 None
El tipo None es el equivalente a null en muchos lenguajes de programación. No contiene métodos y tampoco atributos. Suele utilizarse cuando se crea una variable cuyo valor inicial se desconoce a priori y probablemente será conocido durante la ejecución de un programa. Las funciones que carecen de retorno devuelven por defecto None.
2.3.5 Booleanos
La versión 2.3 de Python incorporó el objeto bool como una clase que hereda de int y cuyos valores posibles son True y False. Versiones previas a la 2.3 no poseían un tipo explícito para el manejo de estos valores que fueron introducidos en la versión 2.2.1 y como sinónimo de los valores 1 y 0 (al igual que en C) que eran usados para indicar valores de verdadero y falso.
Todos los datos en Python pueden ser evaluados como un valor booleano. Por ejemplo, cualquier cadena, lista, tupla, diccionario no vacío, None y dato numérico distinto de cero tiene un valor verdadero (True). Mientras que, cero, cadenas, tuplas, listas y diccionarios vacíos evalúan falso. Considere el siguiente código:
Este código no llega a la sentencia de la función print porque la condición evalua False dado que la lista está vacía. Si se añade un elemento entonces se logra que se ejecute la sentencia que corresponde a la función print.
Igual sucedería en caso de tratarse de un número distinto de cero. En la próxima sección se examinará una estructura de datos muy útil conocida como conjunto (set).
2.3.6 Conjuntos
Los conjuntos fueron introducidos en la versión 2.3 de Python a través del tipo Set y se construyen a partir de una secuencia que se define como argumento de la función set().
Los conjuntos que se crean en Python son conjuntos tradicionales y no multiconjuntos de modo que solo un ejemplar de cada elemento repetido en la secuencia de entrada es incluido en el conjunto resultante y por ende set([1, 2, 3]) es igual a set([1,1, 2, 2, 3]).
Los conjuntos permiten operaciones clásicas como pueden ser la intersección, la unión o la diferencia, todas serán analizadas durante este capítulo.
2.4 Operadores de comparación
Los operadores de comparación son binarios y cada uno de sus argumentos puede ser una expresión que evalúe a un valor de un tipo diferente (numéricos,
cadenas, listas, etc.). La siguiente tabla muestra los operadores de comparación de Python.
operador Descripción
== Devuelve True si los dos operandos son iguales. False en caso contrario.
!= Devuelve True si los dos operandos son diferentes.
False en caso contrario.
<> Ídem a != pero no soportado en la versión 3.1
> Devuelve True si el operador de la izquierda es mayor
que el de la derecha.
< Devuelve True si el operador de la derecha es mayor que el de la izquierda.
>= Devuelve True si el operador de la izquierda es mayor
o igual que el de la derecha.
<= Devuelve True si el operador de la derecha es mayor o
igual que el de la derecha.
Observe el siguiente código donde se puede apreciar el uso de los operadores de comparación.
Los operadores de comparación suelen utilizarse en sentencias condicionales para controlar el flujo de un programa de acuerdo a determinadas condiciones.
2.5 Operadores aritméticos
Los operadores aritméticos al igual que los de comparación cuentan con un operando derecho y uno izquierdo, son binarios. Generalmente se aplican a datos
numéricos aunque el operador de suma (+) también se emplea para concatenar secuencias (cadenas, listas, etc.) según se muestra en el siguiente ejemplo:
La aritmética es una rama de las matemáticas que data de la prehistoria. Entre las operaciones que incluye se encuentran la adición, la resta, la multiplicación, la división, la potenciación y el resto. La siguiente tabla muestra los operadores aritméticos en Python.
Operador Descripción
+ Devuelve la suma de los operandos.
−
Devuelve la resta del
operando de la izquierda por el de la derecha.
/
Devuelve la división del operando de la izquierda por el de la derecha.
* Devuelve la multiplicación de los operandos.
//
Devuelve la división truncada (parte entera del cociente) del operando de la izquierda por el de la derecha.
**
Devuelve el operando
izquierdo elevado a la potencia que representa el operando derecho.
%
Devuelve el resto de la división del operando izquierdo por el operando derecho.
Para ilustrar el uso de estos operadores considere el código que se muestra a continuación:
Todos los operadores excepto el operador de potenciación son asociativos de izquierda a derecha. La potenciación es asociativa de derecha a izquierda.
2.6 Operadores lógicos
Los operadores lógicos de Python son equivalentes a su contrapartida de la lógica proposicional, estos son: la conjunción, la disyunción y la negación. Considerando que en Python muchos de los objetos o datos predefinidos pueden ser evaluados al tipo bool (datos numéricos, cadenas, listas, tuplas) entonces todos estos pueden ser tomados como operandos lógicos. Observe el código que se muestra a continuación:
Para comprender su funcionamiento debe tenerse en cuenta la evaluación a tipo bool que poseen los objetos empleados como operandos. La forma en la que los operadores lógicos devuelven un resultado de verdad a partir de sus operandos es la siguiente:
Operador Operando izq. Operando der. Resultado
or
True True True
False True True
True False True
Operador Operando izq. Operando der. Resultado
and
True True True
False True False
True False False
False False False
Operador Operando Resultado
not True False
False True
Como se puede observar el operador de negación es unario, solo recibe un operando. La tabla que se observa a continuación describe estos operadores.
Operador Descripción
or Disyunción lógica de sus operandos. and Conjunción lógica de sus operandos.
not Negación lógica de su operando.
Los operadores lógicos en Python resultan mucho más expresivos si se comparan con sus homólogos de otros lenguajes. La disyunción en C, por ejemplo, se consigue por medio del operador (||), claramente (or) ofrece la posibilidad de crear sentencias lógicas más legibles y claras.