2.2: Tipos de datos elementales
- Page ID
- 55113
\( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)
\( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)
\( \newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\)
( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\)
\( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\)
\( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\)
\( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\)
\( \newcommand{\Span}{\mathrm{span}}\)
\( \newcommand{\id}{\mathrm{id}}\)
\( \newcommand{\Span}{\mathrm{span}}\)
\( \newcommand{\kernel}{\mathrm{null}\,}\)
\( \newcommand{\range}{\mathrm{range}\,}\)
\( \newcommand{\RealPart}{\mathrm{Re}}\)
\( \newcommand{\ImaginaryPart}{\mathrm{Im}}\)
\( \newcommand{\Argument}{\mathrm{Arg}}\)
\( \newcommand{\norm}[1]{\| #1 \|}\)
\( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\)
\( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\AA}{\unicode[.8,0]{x212B}}\)
\( \newcommand{\vectorA}[1]{\vec{#1}} % arrow\)
\( \newcommand{\vectorAt}[1]{\vec{\text{#1}}} % arrow\)
\( \newcommand{\vectorB}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)
\( \newcommand{\vectorC}[1]{\textbf{#1}} \)
\( \newcommand{\vectorD}[1]{\overrightarrow{#1}} \)
\( \newcommand{\vectorDt}[1]{\overrightarrow{\text{#1}}} \)
\( \newcommand{\vectE}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash{\mathbf {#1}}}} \)
\( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)
\( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)
\(\newcommand{\avec}{\mathbf a}\) \(\newcommand{\bvec}{\mathbf b}\) \(\newcommand{\cvec}{\mathbf c}\) \(\newcommand{\dvec}{\mathbf d}\) \(\newcommand{\dtil}{\widetilde{\mathbf d}}\) \(\newcommand{\evec}{\mathbf e}\) \(\newcommand{\fvec}{\mathbf f}\) \(\newcommand{\nvec}{\mathbf n}\) \(\newcommand{\pvec}{\mathbf p}\) \(\newcommand{\qvec}{\mathbf q}\) \(\newcommand{\svec}{\mathbf s}\) \(\newcommand{\tvec}{\mathbf t}\) \(\newcommand{\uvec}{\mathbf u}\) \(\newcommand{\vvec}{\mathbf v}\) \(\newcommand{\wvec}{\mathbf w}\) \(\newcommand{\xvec}{\mathbf x}\) \(\newcommand{\yvec}{\mathbf y}\) \(\newcommand{\zvec}{\mathbf z}\) \(\newcommand{\rvec}{\mathbf r}\) \(\newcommand{\mvec}{\mathbf m}\) \(\newcommand{\zerovec}{\mathbf 0}\) \(\newcommand{\onevec}{\mathbf 1}\) \(\newcommand{\real}{\mathbb R}\) \(\newcommand{\twovec}[2]{\left[\begin{array}{r}#1 \\ #2 \end{array}\right]}\) \(\newcommand{\ctwovec}[2]{\left[\begin{array}{c}#1 \\ #2 \end{array}\right]}\) \(\newcommand{\threevec}[3]{\left[\begin{array}{r}#1 \\ #2 \\ #3 \end{array}\right]}\) \(\newcommand{\cthreevec}[3]{\left[\begin{array}{c}#1 \\ #2 \\ #3 \end{array}\right]}\) \(\newcommand{\fourvec}[4]{\left[\begin{array}{r}#1 \\ #2 \\ #3 \\ #4 \end{array}\right]}\) \(\newcommand{\cfourvec}[4]{\left[\begin{array}{c}#1 \\ #2 \\ #3 \\ #4 \end{array}\right]}\) \(\newcommand{\fivevec}[5]{\left[\begin{array}{r}#1 \\ #2 \\ #3 \\ #4 \\ #5 \\ \end{array}\right]}\) \(\newcommand{\cfivevec}[5]{\left[\begin{array}{c}#1 \\ #2 \\ #3 \\ #4 \\ #5 \\ \end{array}\right]}\) \(\newcommand{\mattwo}[4]{\left[\begin{array}{rr}#1 \amp #2 \\ #3 \amp #4 \\ \end{array}\right]}\) \(\newcommand{\laspan}[1]{\text{Span}\{#1\}}\) \(\newcommand{\bcal}{\cal B}\) \(\newcommand{\ccal}{\cal C}\) \(\newcommand{\scal}{\cal S}\) \(\newcommand{\wcal}{\cal W}\) \(\newcommand{\ecal}{\cal E}\) \(\newcommand{\coords}[2]{\left\{#1\right\}_{#2}}\) \(\newcommand{\gray}[1]{\color{gray}{#1}}\) \(\newcommand{\lgray}[1]{\color{lightgray}{#1}}\) \(\newcommand{\rank}{\operatorname{rank}}\) \(\newcommand{\row}{\text{Row}}\) \(\newcommand{\col}{\text{Col}}\) \(\renewcommand{\row}{\text{Row}}\) \(\newcommand{\nul}{\text{Nul}}\) \(\newcommand{\var}{\text{Var}}\) \(\newcommand{\corr}{\text{corr}}\) \(\newcommand{\len}[1]{\left|#1\right|}\) \(\newcommand{\bbar}{\overline{\bvec}}\) \(\newcommand{\bhat}{\widehat{\bvec}}\) \(\newcommand{\bperp}{\bvec^\perp}\) \(\newcommand{\xhat}{\widehat{\xvec}}\) \(\newcommand{\vhat}{\widehat{\vvec}}\) \(\newcommand{\uhat}{\widehat{\uvec}}\) \(\newcommand{\what}{\widehat{\wvec}}\) \(\newcommand{\Sighat}{\widehat{\Sigma}}\) \(\newcommand{\lt}{<}\) \(\newcommand{\gt}{>}\) \(\newcommand{\amp}{&}\) \(\definecolor{fillinmathshade}{gray}{0.9}\)Las variables son vitales para casi todos los lenguajes de programación. En Python, las variables son “nombres que hacen referencia a datos”. Los tipos de datos más básicos a los que se puede hacer referencia se definen por cómo funcionan las computadoras contemporáneas y son compartidos por la mayoría de los idiomas.
Enteros, flotadores y booleanos
Considera el entero 10, y el número real 5.64. Resulta que estos dos están representados de manera diferente en el código binario de la computadora, en parte por razones de eficiencia (por ejemplo, almacenar 10
vs. 10.0000000000
). Python y la mayoría de los otros lenguajes consideran que los enteros y los números reales son dos “tipos” diferentes: los números reales se llaman floats (abreviatura de “números de punto flotante”), y los enteros se llaman ints. Asignamos datos como flotadores e ints a variables usando el operador =
.

Mientras estamos en el tema de las variables, los nombres de variables en Python siempre deben comenzar con una letra minúscula y contener solo letras, guiones bajos y números.
Tenga en cuenta que el intérprete ignora #
caracteres y cualquier cosa después de ellos en la línea. [1] Esto nos permite poner “comentarios” en nuestro código. Las líneas en blanco tampoco importan, permitiendo la inserción de líneas en blanco en el código para facilitar la lectura.
Podemos convertir un tipo int en un tipo float usando la función float ()
, que toma un parámetro dentro de los paréntesis:

Del mismo modo, podemos convertir floats a ints usando la función int ()
, que trunca el valor de coma flotante en el punto decimal (así que 5.64 se truncará al int type 5, mientras que -4.67 estaría truncado al int type -4):

Esta información es útil debido a una advertencia particular cuando se trabaja con la mayoría de los lenguajes de programación, Python incluyó: si realizamos operaciones matemáticas usando solo tipos int, el resultado siempre será un int. Así, si queremos que nuestras operaciones devuelvan un valor de punto flotante, primero necesitamos convertir al menos una de las entradas del lado derecho a un tipo flotante. Afortunadamente, podemos hacer esto en línea:

En la última línea anterior, vemos que las expresiones matemáticas se pueden agrupar con paréntesis de la manera habitual (para anular el orden estándar de las operaciones si es necesario), y si una subexpresión devuelve un float, entonces viajará por la cadena para inducir matemáticas de punto flotante para el resto de la expresión. [2]
Otra propiedad de importancia es que el lado derecho de una tarea se evalúa antes de que ocurra la asignación.

Aparte de la suma y resta habituales, otros operadores matemáticos de nota incluyen **
para potencias exponenciales y%
para módulo (para indicar un resto después de la división entera, por ejemplo, 7% 3
es 1
, 8% 3
es 2
, 9% 3
es 0
, y así sucesivamente).

Observe que hemos reutilizado las variables a
, b
y c
; esto es completamente permisible, pero debemos recordar que ahora se refieren a diferentes datos. (Recordemos que una variable en Python es un nombre que hace referencia a, o hace referencia, a algunos datos.) En general, la ejecución de líneas dentro del mismo archivo (o celda en un cuaderno IPython) ocurre de manera ordenada de arriba a abajo, aunque más adelante veremos “estructuras de control” que alteran este flujo.
Los booleanos son tipos de datos simples que contienen el valor especial True
o el valor especial False
. Muchas funciones devuelven Booleanos, al igual que las comparaciones:

Por ahora, no vamos a usar mucho los valores booleanos, pero más adelante serán importantes para controlar el flujo de nuestros programas.
Cuerdas
Las cadenas, que contienen secuencias de letras, dígitos y otros caracteres, son los tipos de datos básicos más interesantes. [3] Podemos especificar el contenido usando comillas simples o dobles, lo que puede ser útil si queremos que la cadena en sí contenga una comilla. Alternativamente, podemos escapar de caracteres impares como comillas si confunden al intérprete mientras intenta analizar el archivo.

Las cadenas se pueden agregar junto con +
para concatenerlas, lo que da como resultado que se devuelva una nueva cadena para que pueda asignarse a una variable. La función print ()
, en su forma más simple, toma como parámetro un solo valor como una cadena. Esta podría ser una variable que se refiera a un dato, o el resultado de un cálculo que devuelva uno:

Sin embargo, no podemos concatenar cadenas con tipos de datos que no son cadenas.

Ejecutar el código anterior resultaría en un TypeError: no se puede concatenar los objetos 'str' y 'float'
, y se reportaría el número de línea infractor. En general, el error real en tu código podría estar antes de la línea que informa el error. Este ejemplo de error en particular no ocurriría si hubiéramos especificado height = “5.5"
en la línea anterior, porque dos cadenas se pueden concatenar con éxito.
Afortunadamente, la mayoría de los tipos de datos incorporados en Python se pueden convertir en una cadena (o una cadena que los describe) usando la función str ()
, que devuelve una cadena.

Como lo ilustra lo anterior, podemos elegir en algunos casos almacenar el resultado de una expresión en una variable para su uso posterior, o tal vez deseemos usar una expresión más compleja directamente. La elección es un equilibrio entre código verboso y código menos verboso, cualquiera de los cuales puede mejorar la legibilidad. Deberías usar lo que tenga más sentido para ti, ¡la persona con más probabilidades de tener que leer el código más tarde!
Python facilita la extracción de una cadena de un solo carácter de una cadena usando corchetes o sintaxis “index”. Recuerda que en Python, la primera letra de una cadena ocurre en el índice 0
.

El uso de corchetes también se conoce como sintaxis “slice”, porque podemos ellos extraer un slice (substring) de una cadena con la siguiente sintaxis: string_var [begin_index:end_index]
. Nuevamente, la indexación de una cadena comienza en 0
. Porque las cosas no pueden ser demasiado fáciles, el índice inicial es inclusivo, mientras que el índice final es exclusivo.

Una buena manera de recordar este poco confuso de sintaxis es pensar que los índices ocurren entre las letras.

Si una cadena parece que podría convertirse a un tipo int o float, probablemente pueda ser con las funciones de conversión float ()
o int ()
. Sin embargo, si tal conversión no tiene sentido, Python se estrellará con un error. Por ejemplo, la última línea de abajo producirá el error ValueError: could not convert string to float: XY_2.7Q
.

Para obtener la longitud de una cadena, podemos usar la función len ()
, que devuelve un int. Podemos usar esto junto con la sintaxis []
para obtener la última letra de una cadena, aunque no sepamos la longitud de la cadena antes de que se ejecute el programa. Debemos recordar, sin embargo, que el índice del último carácter es uno menos que la longitud, basado en las reglas de indexación.

Del mismo modo, si queremos una subcadena desde la posición 2
hasta el final de la cadena, necesitamos recordar las peculiaridades de la notación []
slice, que es inclusive:exclusive.
Inmutabilidad
En algunos idiomas es posible cambiar el contenido de una cadena después de haber sido creada. En Python y algunos otros lenguajes, este no es el caso, y se dice que las cadenas son inmutables. Se dice que los datos son inmutables si no pueden ser alterados después de su creación inicial. La siguiente línea de código, por ejemplo, causaría un error como TypeError: 'str' object does not support item assignment
:

Lenguajes como Python y Java hacen que las cadenas sean inmutables por una variedad de razones, incluida la eficiencia computacional y como salvaguardia para evitar ciertas clases comunes de errores de programación. Para la biología computacional, donde a menudo deseamos modificar cadenas que representan secuencias biológicas, esto es una molestia. Aprenderemos varias estrategias para solucionar este problema en futuros capítulos.
En muchos casos, podemos hacer que parezca que estamos cambiando el contenido de algunos datos de cadena reutilizando el nombre de la variable. En el siguiente código, estamos definiendo cadenas seqa
y seqb
, así como seqc
como la concatenación de estas, y luego seqd
como una subcadena de seqc
. Finalmente, reutilizamos el nombre de la variable seqa
para hacer referencia a diferentes datos (que se copian del original).

Así es como podríamos representar estas variables y los datos almacenados en la memoria, tanto antes como después de la reasignación de seqa
.
Debido a que la cadena “ACTAG”
es inmutable, redefinir seqa
da como resultado que se cree una pieza de datos completamente diferente. La cadena original “ACTAG”
seguirá existiendo en la memoria (RAM) por poco tiempo, pero debido a que no es accesible a través de ninguna variable, Python eventualmente la limpiará para hacer espacio en la memoria en un proceso conocido como recolección de basura. [4] La recolección de basura es un proceso automático y periódico de desasignación de memoria utilizada por datos que ya no son accesibles (y por lo tanto ya no son necesarios) por el programa.
Esta inmutabilidad de cadenas podría dar como resultado un código que tarde mucho más en ejecutarse de lo esperado, ya que la concatenación de cadenas da como resultado la copia de datos (ver los resultados de seqc = seqa + seqb
arriba). Por ejemplo, si tuviéramos un comando que concatenara cadenas cromosómicas (millones de letras cada una) para crear una cadena genómica, genoma = chr1 + chr2 + chr3 + chr4
, ¡el resultado sería una copia de los cuatro cromosomas que se están creando en la memoria! Por otro lado, en muchos casos, Python puede utilizar la inmutabilidad de las cadenas a su favor. Supongamos, por ejemplo, que queríamos obtener una subcadena grande de una cadena grande, centromere_region = chr1 [0:1500000]
. En este caso, Python no necesita hacer una copia de la subcadena en la memoria. Debido a que la cadena original nunca puede cambiar, todo lo que necesita es algo de contabilidad detrás de escena para recordar que la variable centromere_region
está asociada con parte de las referencias de cadena chr1
. Es por ello que seqd
en la figura anterior no duplica datos de seqc
.
Ninguna de esta discusión implica que en este momento deba preocuparse por la eficiencia computacional de estas operaciones. Más bien, el concepto de inmutabilidad y la definición de una variable (en Python) como un “nombre que se refiere a algunos datos” son lo suficientemente importantes como para garantizar una discusión formal.
Ejercicios
- Cree y ejecute un programa Python que utilice enteros, flotantes y cadenas, y convierta entre estos tipos. Intente usar la función
bool ()
para convertir un entero, flotante o cadena a booleano e imprimir los resultados. ¿Qué tipos de enteros, flotantes y cadenas se convierten en unFalse
booleano y qué tipos se convierten aTrue
? - Sabemos que no podemos usar el operador
+
para concatenar un tipo de cadena y un tipo entero, pero ¿qué sucede cuando multiplicamos una cadena por un entero? (Esta es una característica que es bastante específica de Python). - ¿Qué sucede cuando intentas usar un tipo flotante como índice en una cadena usando la sintaxis
[]
? ¿Qué sucede cuando usas un entero negativo? - Supongamos que tiene una cadena de secuencia como variable, como
seq = “ACTAGATGA”
. Usando solo los conceptos de este capítulo, escribe algún código que use la variableseq
para crear dos nuevas variables,primera_mitad y
que contengan la primera mitad (redondeada hacia abajo) y la segunda mitad (redondeada hacia arriba) desegunda_mitad
seq
. Al imprimirse, estos dos deben imprimir“ACTA”
y“GATGA”
, respectivamente.Es importante destacar que tu código debería funcionar sin importar la cadena a la que se refiere
seq
, sin cambiar ningún otro código, siempre y cuando la longitud de la cadena sea de al menos dos letras. Por ejemplo, siseq = “TACTTG”
, entonces el mismo código debería resultar enfirst_half
refiriéndose a“TAC”
ysecond_half
refiriéndose a“TTG”
.
- Los símbolos
#
se ignoran a menos que ocurran dentro de un par de comillas. Técnicamente, el intérprete también ignora el#!
línea, pero es necesario para ayudar al sistema a encontrar al intérprete en el proceso de ejecución. - Esto no es cierto en Python 3.0 y posteriores; por ejemplo, 10/3 devolverá el flotador 3.33333.
- A diferencia de C y algunos otros lenguajes, Python no tiene un tipo de datos “char” específicamente para almacenar un solo carácter.
- La recolección de basura es una característica común de lenguajes de alto nivel como Python, aunque algunos lenguajes compilados también lo admiten. C no: se requiere que los programadores se aseguren de que todos los datos no utilizados se borran durante la ejecución del programa. No hacerlo se conoce como una “fuga de memoria” y causa muchos bloqueos de software del mundo real.