Clase 2: Modularización y tipos compuestos

Nota

Escenas del capítulo anterior:

En la clase anterior preparamos la infraestructura:

  • Instalamos los programas y paquetes necesarios.

  • Aprendimos como ejecutar: una consola usual, de ipython, o iniciar un jupyter notebook

  • Aprendimos a utilizar la consola como una calculadora

  • Vimos algunos comandos mágicos y como enviar comandos al sistema operativo

  • Aprendimos como obtener ayuda

  • Iniciamos los primeros pasos del lenguaje

Veamos un ejemplo completo de un programa (semi-trivial):

# Definición de los datos
r = 9.
pi = 3.14159
#
# Cálculos
A = pi*r**2
As = 4 * A
V = 4*A*r/3
#
# Salida de los resultados
print("Para un círculo de radio",r,"cm, el área es",A,"cm²")
print("Para una esfera de radio",r,"cm, el área es",As,"cm²")
print("Para una esfera de radio",r,"cm, el volumen es",V,"cm³")

En este ejemplo simple, definimos algunas variables con los datos del problema (r y pi), realizamos cálculos y sacamos por pantalla los resultados. A diferencia de otros lenguajes, python no necesita una estructura rígida, con definición de un programa principal.

Otro punto importante de este ejemplo es el uso de comentarios. El caracter “#” inicia un comentario de línea, y el intérprete de python ignora todos lo que viene a continuación hasta que encuentra una nueva línea.

Modularización y encapsulado

Una característica importante de la programación es la posibilidad de definir partes del código para realizar alguna tarea específica y poder reutilizarla. En Python, una de las maneras más efectivas de hacer esto es mediante la definición de funciones. Ya vimos un ejemplo, con la función print(), que se usa para imprimir valores a pantalla (por defecto) o un archivo. Existen otras funciones ya definidas en Python (len(), max(), min(), abs(), etc). Puede ver la lista completa en la documentación.

Definición básica de funciones

Tomemos el ejemplo del programa anterior para definir una función que calcule el área de un disco

def area_disco(r):
  """Cálculo del área de un círculo de radio `r`"""
  # Definición de constantes
  pi = 3.141593
  # Cálculo
  A = pi * r**2
  return A

Puntos a notar:

  • Las funciones se definen utilizando la palabra def seguida por el nombre.

  • A continuación, entre paréntesis se escriben los argumentos, en este caso el radio r,

  • La función devuelve algo; puede ser uno o más valores.

  • Lo que devuelve la función se especifica mediante la palabra reservada return (en este caso A que es un valor real). Si es más de un valor, se separan con comas. Si una función no devuelve algo explícitamente, entonces devuelve None.

  • Al principio de la definición de la función se escribe el string de documentación.

help(area_disco)
Help on function area_disco in module __main__:

area_disco(r)
    Cálculo del área de un círculo de radio r
R = 2
Area = area_disco(R)
print("Para un círculo de radio", R, "cm, el área es",Area,"cm²")
Para un círculo de radio 2 cm, el área es 12.566372 cm²
print("Para un círculo de radio", 3, "cm, el área es",area_disco(3),"cm²")
Para un círculo de radio 3 cm, el área es 28.274337 cm²

Módulos

Los módulos son el mecanismo de Python para reusar código. Existen varios módulos que son parte de la biblioteca standard para distintos tipos de aplicaciones. Además existe un repositorio en la que contribuye la comunidad, con bibliotecas para muchos usos diversos.

El uso de módulos es muy simple, para poder aprovecharlo necesitaremos saber dos cosas:

  • Qué funciones están ya definidas y listas para usar

  • Cómo acceder a ellas

Empecemos con la segunda cuestión. Para utilizar las funciones debemos importarlas en la forma import modulo, donde modulo es el nombre que queremos importar.

Esto nos lleva a la primera cuestión: cómo saber ese nombre, y que funciones están disponibles. La respuesta es: la documentación.

Una vez importado, podemos utilizar constantes y funciones definidas en el módulo con la notación “de punto”: modulo.funcion().

Módulo math

El módulo math contiene las funciones más comunes (trigonométricas, exponenciales, logaritmos, etc) para operar sobre números de punto flotante, y algunas constantes importantes (pi, e, etc). En realidad es una interface a la biblioteca math en C.

import math
# algunas constantes y funciones elementales
raiz5pi= math.sqrt(5*math.pi)
print (raiz5pi, math.floor(raiz5pi), math.ceil(raiz5pi))
print (math.e, math.floor(math.e), math.ceil(math.e))
# otras funciones elementales
print (math.log(1024,2), math.log(27,3))
print (math.factorial(7), math.factorial(9), math.factorial(10))
print ('Combinatorio: C(6,2):',math.factorial(6)/(math.factorial(4)*math.factorial(2)))
3.963327297606011 3 4
2.718281828459045 2 3
10.0 3.0
5040 362880 3628800
Combinatorio: C(6,2): 15.0

A veces, sólo necesitamos unas pocas funciones de un módulo. Entonces para abreviar la notación combiene importar sólo lo que vamos a usar, usando la notación:

from xxx import yyy

from math import sqrt, pi, log
import math
raiz5pi = sqrt(5*pi)
print (log(1024, 2))
print (raiz5pi, math.floor(raiz5pi))
10.0
3.963327297606011 3
import math as m
m.sqrt(3.2)
1.7888543819998317
import math
print(math.sqrt(-1))
---------------------------------------------------------------------------

ValueError                                Traceback (most recent call last)

Cell In[9], line 2
      1 import math
----> 2 print(math.sqrt(-1))


ValueError: math domain error

Módulo cmath

El módulo math no está diseñado para trabajar con números complejos, para ello existe el módulo cmath

import cmath
print('Usando cmath (-1)^0.5=', cmath.sqrt(-1))
print(cmath.cos(cmath.pi/3 + 2j))
Usando cmath (-1)^0.5= 1j
(1.8810978455418161-3.1409532491755083j)

Si queremos calcular la fase (el ángulo que forma con el eje x) podemos usar la función phase

z = 1 + 0.5j
cmath.phase(z)                  # Resultado en radianes
0.4636476090008061
math.degrees(cmath.phase(z))    # Resultado en grados
26.56505117707799

Ejercicios 02 (a)

  1. Escriba funciones que calculen:

  • El volumen de una esfera

  • El volumen de una caja de lados L1, L2, L3

  1. Escriba una función que tome como argumentos tres valores: a, b, c y calcule los ceros (raíces) del polinomio \(a x^{2} + b x + c\).

  2. Considere un polígono regular de \(N\) lados inscripto en un círculo de radio unidad:

    • Escriba una función que tome como argumento el número de lados \(N\) y calcule el ángulo interior del polígono regular correspondiente (por ejemplo el de un triángulo es 60 grados, de un cuadrado es 90 grados, y de un pentágono es 108 grados). Pruebe su función para valores de \(N= 3, 5, 6, 8, 9, 10, 12\).

    • ¿Puede calcular la longitud del lado de los polígonos regulares si se encuentran inscriptos en un círculo de radio unidad?

En todos los casos, pruebe las funciones escritas


Tipos simples: Números

  • Números Enteros

  • Números Reales o de punto flotante

  • Números Complejos

Mencionamos anteriormente que todos las entidades en Python son objetos, que tienen al menos tres atributos: tipo, valor e identidad. Pero además, puede tener otros atributos como datos o métodos. Por ejemplo los números enteros, unos de los tipos más simples que usaremos, tienen métodos que pueden resultar útiles en algunos contextos.

a = 3                           # Números enteros
print(type(a), a.bit_length(), sep="\n")
<class 'int'>
2
b = 127
print(type(b))
print(b.bit_length())
<class 'int'>
7

En estos casos, usamos el método bit_length de los enteros, que nos dice cuántos bits son necesarios para representar un número. Para verlo utilicemos la función bin() que nos da la representación en binario de un número entero

# bin nos da la representación en binarios
print(a, "=", bin(a), "->", a.bit_length(),"bits")
print(b, "=", bin(b), "->", b.bit_length(),"bits")
3 = 0b11 -> 2 bits
127 = 0b1111111 -> 7 bits

Esto nos dice que el número 3 se puede representar con dos bits, y que para representar el número 127 se necesitan 7 bits.

Los números de punto flotante también tienen algunos métodos definidos. Por ejemplo podemos saber si un número flotante corresponde a un entero:

b = -3.0
b.is_integer()
True
c = 142.25
c.is_integer()
False

o podemos expresarlo como el cociente de dos enteros, o en forma hexadecimal

c.as_integer_ratio()
(569, 4)
s = c.hex()
print(s)
0x1.1c80000000000p+7

Acá la notación, compartida con otros lenguajes (C, Java), significa:

[sign] ['0x'] integer ['.' fraction] ['p' exponent]

Entonces ‘0x1.1c8p+7’ corresponde a:

(1 + 1./16 + 12./16**2 + 8./16**3)*2.0**7
142.25

Recordemos, como último ejemplo, los números complejos:

z = 1 + 2j
zc = z.conjugate()              # Método que devuelve el conjugado
zr = z.real                     # Componente, parte real
zi = z.imag                     # Componente, parte imaginaria
print(z, zc, zr, zi, zc.imag)
(1+2j) (1-2j) 1.0 2.0 -2.0

Tipos compuestos

En Python, además de los tipos simples (números y booleanos, entre ellos) existen tipos compuestos, que pueden contener más de un valor de algún tipo. Entre los tipos compuestos más importantes vamos a referirnos a:

  • Se pueden definir con comillas dobles ( ” ), comillas simples ( ’ ), o tres comillas (simples o dobles). Comillas (dobles) y comillas simples producen el mismo resultado. Sólo debe asegurarse que se utiliza el mismo tipo para abrir y para cerrar el string
    Ejemplo: s = "abc" (el elemento s[0] tiene el valor "a").
  • Las listas son tipos que pueden contener más de un elemento de cualquier tipo. Los tipos de los elementos pueden ser diferentes. Las listas se definen separando los diferentes valores con comas, encerrados entre corchetes. Se puede referir a un elemento por su índice.
    Ejemplo: L = ["a",1, 0.5 + 1j] (el elemento L[0] es igual al string "a").
  • Las tuplas se definen de la misma manera que las listas pero con paréntesis en lugar de corchetes. Ejemplo: T = ("a",1, 0.5 + 1j).
  • Los diccionarios son contenedores a cuyos elementos se los identifica con un nombre (key) en lugar de un índice. Se los puede definir dando los pares key:value entre llaves
    Ejemplo: D = {'a': 1, 'b': 2, 1: 'hola', 2: 3.14} (el elemento D['a'] es igual al número 1).

Strings: Secuencias de caracteres

Una cadena o string es una secuencia de caracteres (letras, “números”, símbolos).

Se pueden definir con comillas, comillas simples, o tres comillas (simples o dobles). Comillas simples o dobles producen el mismo resultado. Sólo debe asegurarse que se utilizan el mismo tipo para abrir y para cerrar el string

Triple comillas (simples o dobles) sirven para incluir una cadena de caracteres en forma textual, incluyendo saltos de líneas.

saludo = 'Hola Mundo'           # Definición usando comillas simples
saludo2 = "Hola Mundo"          # Definición usando comillas dobles
saludo, saludo2
('Hola Mundo', 'Hola Mundo')
saludo == saludo2
True

Los strings se pueden definir equivalentemente usando comillas simples o dobles. De esta manera es fácil incluir comillas dentro de los strings

otro= "that's all"
dijo = '"Cómo te va" dijo el murguista a la muchacha'
print(otro)
that's all
print(dijo)
"Cómo te va" dijo el murguista a la muchacha
respondio = "Le dijo \"Bien\" y lo dejó como si nada"
print(respondio)
Le dijo "Bien" y lo dejó como si nada

Para definir strings que contengan más de una línea, manteniendo el formato, se pueden utilizar tres comillas (dobles o simples):

Texto_largo = '''Aquí me pongo a cantar
  Al compás de la vigüela,
Que el hombre que lo desvela
  Una pena estraordinaria
Como la ave solitaria
  Con el cantar se consuela.'''
print (Texto_largo,'\n')
Aquí me pongo a cantar
  Al compás de la vigüela,
Que el hombre que lo desvela
  Una pena estraordinaria
Como la ave solitaria
  Con el cantar se consuela.
Texto_largo
'Aquí me pongo a cantarn  Al compás de la vigüela,nQue el hombre que lo desvelan  Una pena estraordinarianComo la ave solitarian  Con el cantar se consuela.'

En Python se puede utilizar cualquier caracter que pueda ingresarse por teclado, ya que por default Python-3 trabaja usando la codificación UTF-8, que incluye todos los símbolos que se nos ocurran. Por ejemplo:

# Un ejemplo que puede interesarnos un poco más:
label = "σ = λ T/ µ + π · δξ"
print('tipo de label: ', type(label))
print ('Resultados corresponden a:', label, ' (en m/s²)')
tipo de label:  <class 'str'>
Resultados corresponden a: σ = λ T/ µ + π · δξ  (en m/s²)

Operaciones

En Python ya hay definidas algunas operaciones que involucran strings como la suma (composición o concatenación) y el producto por enteros (repetición).

s = saludo + ' -> ' + otro + '\t'
s = s + "chau"
print (s) #  Suma de strings
Hola Mundo -> that's all    chau

Como vemos la suma de strings es simplemente la concatenación de los argumentos. La multiplicación de un entero n por un string es simplemente la suma del string n veces:

a = '1'
b = 1
print(a, type(a))
print(b, type(b))
1 <class 'str'>
1 <class 'int'>
print ("Multiplicación por enteros de strings:", 7*a)
print ("Multiplicación por enteros de enteros:", 7*b)
Multiplicación por enteros de strings: 1111111
Multiplicación por enteros de enteros: 7

La longitud de una cadena de caracteres (como de otros objetos) se puede calcular con la función len()

print ('longitud del saludo =', len(saludo), 'caracteres')
longitud del saludo = 10 caracteres

Por ejemplo, podemos usar estas operaciones para realizar el centrado manual de una frase:

titulo = "Centrado manual simple"
n = int((60-len(titulo))//2)    # Para un ancho de 60 caracteres
print ((n)*'<', titulo ,(n)*'>')
#
saludo = 'Hola Mundo'
n = int((60-len(saludo))//2)    # Para un ancho de 60 caracteres
print (n*'*', saludo, n*'*')
<<<<<<<<<<<<<<<<<<< Centrado manual simple >>>>>>>>>>>>>>>>>>>
********************* Hola Mundo *********************

Iteración y Métodos de Strings

Los strings poseen varias cualidades y funcionalidades. Por ejemplo:

  • Se puede iterar sobre ellos, y también quedarse con sólo una parte (slicing)

  • Tienen métodos (funciones que se aplican a su dueño)

Veamos en primer lugar cómo se hace para seleccionar parte de un string

Indexado de strings

Podemos referirnos a un caracter o una parte de una cadena de caracteres mediante su índice. Los índices en Python empiezan en 0.

s = "0123456789"
print ('Primer caracter  :', s[0])
print ("Segundo caracter :", s[1])
Primer caracter  : 0
Segundo caracter : 1

Si queremos empezar desde el final utilizamos índices negativos. El índice “-1” corresponde al último caracter.n

print ("El último caracter :", s[-1])
print ("El anteúltimo caracter :", s[-2])
El último caracter : 9
El anteúltimo caracter : 8

También podemos elegir un subconjunto de caracteres:

print ('Los tres primeros:          ', s[0:3])
print ('Todos a partir del tercero: ', s[3:])
print ('Los últimos dos:            ', s[-2:])
print ('Todos menos los últimos dos:', s[:-2])
Los tres primeros:           012
Todos a partir del tercero:  3456789
Los últimos dos:             89
Todos menos los últimos dos: 01234567

Estas “subcadenas” son cadenas de caracteres, y por lo tanto pueden utilizarse de la misma manera que cualquier otra cadena:

print (s[:3] + s[-2:])
01289

La selección de elementos y subcadenas de una cadena s tiene la forma general

s[i: f: p]

donde i, f, p son enteros. La notación se refiere a la subcadena empezando en el índice i, hasta el índice f recorriendo con paso p. Casos particulares de esta notación son:

  • Un índice simple. Por ejemplo s[3] se refiere al tercer elemento.

  • Un índice negativo se cuenta desde el final, empezando desde -1.

  • Si el paso p no está presente el valor por defecto es 1. Ejemplo: s[2:4] = s[2:4:1].

  • Si se omite el primer índice, el valor asumido es 0. Ejemplo: s[:2:1] = s[0:2:1].

  • Si se omite el segundo índice, el valor asumido es -1. Ejemplo: s[1::1] = s[1:-1:1].

  • Notar que puede omitirse más de un índice. Ejemplo: s[::2] = s[0:-1:2].

print(s)
print(s[0:5:2])
print (s[::2])
print (s[::-1])
print (s[::-3])
0123456789
024
02468
9876543210
9630

Veamos algunas utilidades que se pueden aplicar sobre un string:

a = "La mar estaba serena!"
print(a)
La mar estaba serena!

Por ejemplo, en python es muy fácil reemplazar una cadena por otra usando el método de strings replace()

b = a.replace('e','a')
print(b)
La mar astaba sarana!

o separar las palabras:

print(a.split())
['La', 'mar', 'estaba', 'serena!']
print(a.split('s'))
['La mar e', 'taba ', 'erena!']

En este caso, tanto replace() como split() son métodos que ya están definidos para los strings.

Recordemos que un método es una función que está definida junto con el tipo de objeto. En este caso el string. Hay más información sobre todos los métodos de las cadenas de caracteres en: String Methods

Veamos algunos ejemplos más:

Buscar y reemplazar cosas en un string:

a.find('e')
7
a.find('x')
-1
a.find('e',8)
15
a.find('re')
16

El método find(sub[, start[, end]]) -> int busca el substring sub empezando con el índice start (argumento opcional) y finalizando en el índice end (argumento opcional, que sólo puede aparecer si también aparece start). Devuelve el índice donde inicial es substring.

Formato de strings

En python se le puede dar formato a los strings de distintas maneras. Vamos a ver dos opciones: - Uso del método format - Uso de “f-strings”

El método format() es una función que busca en el strings las llaves y las reemplaza por los argumentos. Veamos esto con algunos ejemplos:

a = 2024
m = 'Feb'
d = 6
s = "Hoy es el día {} de {} de {}".format(d, m, a)
print(s)
print("Hoy es el día {}/{}/{}".format(d,m,a))
print("Hoy es el día {0}/{1}/{2}".format(d,m,a))
print("Hoy es el día {2}/{1}/{0}".format(d,m,a))
Hoy es el día 6 de Feb de 2024
Hoy es el día 6/Feb/2024
Hoy es el día 6/Feb/2024
Hoy es el día 2024/Feb/6
raiz = "datos-{}-{}-{}.dat"
fname = raiz.format(a,m,d)
print(fname)
datos-2024-Feb-6.dat

Más recientemente se ha implementado en Python una forma más directa de intercalar datos con caracteres literales, mediante f-strings, que permite una sintaxis más compacta. Comparemos las dos maneras:

pi = 3.141592653589793
s1 = "El valor de π es {}".format(pi)
s2 = "El valor de π con cuatro decimales es {0:.4f}".format(pi)
print(s1)
print(s2)
El valor de π es 3.141592653589793
El valor de π con cuatro decimales es 3.1416
print("El valor de 2π con seis decimales es {:012.6f}".format(2*pi))
El valor de 2π con seis decimales es 00006.283185

Para darle formato a números enteros usamos el caracter ‘d’ (decimal)

print("{:03d}".format(5))
print("{:3d}".format(5))
005
  5
t = f"el valor de π es {pi}"
print(t)
el valor de π es 3.141592653589793

Podemos obtener estos mismos resultados usando “f-strings”

print(f"el valor de π es {pi}")
print(f"El valor de π con seis decimales es {pi:.4f}")
print(f"El valor de 2π con seis decimales es {2*pi:012.6f}")
print(f"{5:03d}")
print(f"{5:3d}")
el valor de π es 3.141592653589793
El valor de π con seis decimales es 3.1416
El valor de 2π con seis decimales es 00006.283185
005
  5
fname = f"datos-{a}-{m}-{d}.dat"
print(fname)
datos-2024-Feb-6.dat

Conversión de tipos

Como comentamos anteriormente, y se ve en los ejemplos anteriores, uno no define el tipo de variable a-priori sino que queda definido al asignársele un valor (por ejemplo a=3 define a como una variable del tipo entero).

a = 3                           # a es entero
b = 3.1                         # b es real
c = 3 + 0j                      # c es complejo
print ("a es de tipo {0}\nb es de tipo {1}\nc es de tipo {2}".format(type(a), type(b), type(c)))
print ("'a + b' es de tipo {0} y 'a + c' es de tipo {1}".format(type(a+b), type(a+c)))
a es de tipo <class 'int'>
b es de tipo <class 'float'>
c es de tipo <class 'complex'>
'a + b' es de tipo <class 'float'> y 'a + c' es de tipo <class 'complex'>

Si bien Python hace la conversión de tipos de variables en algunos casos, no hace magia, no puede adivinar nuestra intención si no la explicitamos.

print (1+'1')
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

Cell In[60], line 1
----> 1 print (1+'1')


TypeError: unsupported operand type(s) for +: 'int' and 'str'

Sin embargo, si le decimos explícitamente qué conversión queremos, todo funciona bien

print (str(1) + '1')
print (1 + int('1'))
print (1 + float('1.e5'))
11
2
100001.0
# a menos que nosotros **nos equivoquemos explícitamente**
print (1 + int('z'))
---------------------------------------------------------------------------

ValueError                                Traceback (most recent call last)

Cell In[62], line 2
      1 # a menos que nosotros **nos equivoquemos explícitamente**
----> 2 print (1 + int('z'))


ValueError: invalid literal for int() with base 10: 'z'

Ejercicios 02 (b)

  1. Para la cadena de caracteres:

s = '''Aquí me pongo a cantar
Al compás de la vigüela,
Que el hombre que lo desvela
Una pena estraordinaria
Como la ave solitaria
Con el cantar se consuela.'''
  • Forme un nuevo string de 10 caracteres que contenga los 5 primeros y los 5 últimos del string anterior s. Imprima por pantalla el nuevo string.

  • Forme un nuevo string que contenga los 10 caracteres centrales de s (utilizando un método que pueda aplicarse a otros strings también). Imprima por pantalla el nuevo string.

  • Cuente la cantidad de veces que aparecen los substrings es, la, que, co, en los siguientes dos casos: distinguiendo entre mayúsculas y minúsculas, y no distinguiendo. Imprima el resultado.

  • Cambie todas las letras “m” por “n” y todas las letras “n” por “m” en s. Imprima el resultado por pantalla.

  1. Utilizando funciones y métodos de strings en la cadena de caracteres:

    s1='En un lugar de la Mancha de cuyo nombre no quiero acordarme'
    
  • Obtenga la cantidad de caracteres.

  • Imprima la frase anterior pero con cada palabra empezando en mayúsculas.

  • Cuente cuantas letras ‘a’ tiene la frase, ¿cuántas vocales tiene?

  1. Centrado manual de frases

    1. Utilizando la función len() centre una frase corta en una pantalla de 80 caracteres. Utilice la frase: “Un ejercicio con cadena de caracteres”

    2. Agregue subrayado a la frase anterior

    3. Escriba una función que centre y subraye una frase dada como argumento. Se espera obtener algo así:

      Un ejercicio con cadena de caracteres
      -------------------------------------
      
    4. Repita el punto anterior utilizando métodos de strings


Veamos como obtener ayuda sobre un tipo (en este caso strings)

s = ""
help(s)  # Equivalentemente, se puede usar: help(str)
Help on class str in module builtins:

class str(object)
 |  str(object='') -> str
 |  str(bytes_or_buffer[, encoding[, errors]]) -> str
 |
 |  Create a new string object from the given object. If encoding or
 |  errors is specified, then the object must expose a data buffer
 |  that will be decoded using the given encoding and error handler.
 |  Otherwise, returns the result of object.__str__() (if defined)
 |  or repr(object).
 |  encoding defaults to sys.getdefaultencoding().
 |  errors defaults to 'strict'.
 |
 |  Methods defined here:
 |
 |  __add__(self, value, /)
 |      Return self+value.
 |
 |  __contains__(self, key, /)
 |      Return key in self.
 |
 |  __eq__(self, value, /)
 |      Return self==value.
 |
 |  __format__(self, format_spec, /)
 |      Return a formatted version of the string as described by format_spec.
 |
 |  __ge__(self, value, /)
 |      Return self>=value.
 |
 |  __getattribute__(self, name, /)
 |      Return getattr(self, name).
 |
 |  __getitem__(self, key, /)
 |      Return self[key].
 |
 |  __getnewargs__(...)
 |
 |  __gt__(self, value, /)
 |      Return self>value.
 |
 |  __hash__(self, /)
 |      Return hash(self).
 |
 |  __iter__(self, /)
 |      Implement iter(self).
 |
 |  __le__(self, value, /)
 |      Return self<=value.
 |
 |  __len__(self, /)
 |      Return len(self).
 |
 |  __lt__(self, value, /)
 |      Return self<value.
 |
 |  __mod__(self, value, /)
 |      Return self%value.
 |
 |  __mul__(self, value, /)
 |      Return self*value.
 |
 |  __ne__(self, value, /)
 |      Return self!=value.
 |
 |  __repr__(self, /)
 |      Return repr(self).
 |
 |  __rmod__(self, value, /)
 |      Return value%self.
 |
 |  __rmul__(self, value, /)
 |      Return value*self.
 |
 |  __sizeof__(self, /)
 |      Return the size of the string in memory, in bytes.
 |
 |  __str__(self, /)
 |      Return str(self).
 |
 |  capitalize(self, /)
 |      Return a capitalized version of the string.
 |
 |      More specifically, make the first character have upper case and the rest lower
 |      case.
 |
 |  casefold(self, /)
 |      Return a version of the string suitable for caseless comparisons.
 |
 |  center(self, width, fillchar=' ', /)
 |      Return a centered string of length width.
 |
 |      Padding is done using the specified fill character (default is a space).
 |
 |  count(...)
 |      S.count(sub[, start[, end]]) -> int
 |
 |      Return the number of non-overlapping occurrences of substring sub in
 |      string S[start:end].  Optional arguments start and end are
 |      interpreted as in slice notation.
 |
 |  encode(self, /, encoding='utf-8', errors='strict')
 |      Encode the string using the codec registered for encoding.
 |
 |      encoding
 |        The encoding in which to encode the string.
 |      errors
 |        The error handling scheme to use for encoding errors.
 |        The default is 'strict' meaning that encoding errors raise a
 |        UnicodeEncodeError.  Other possible values are 'ignore', 'replace' and
 |        'xmlcharrefreplace' as well as any other name registered with
 |        codecs.register_error that can handle UnicodeEncodeErrors.
 |
 |  endswith(...)
 |      S.endswith(suffix[, start[, end]]) -> bool
 |
 |      Return True if S ends with the specified suffix, False otherwise.
 |      With optional start, test S beginning at that position.
 |      With optional end, stop comparing S at that position.
 |      suffix can also be a tuple of strings to try.
 |
 |  expandtabs(self, /, tabsize=8)
 |      Return a copy where all tab characters are expanded using spaces.
 |
 |      If tabsize is not given, a tab size of 8 characters is assumed.
 |
 |  find(...)
 |      S.find(sub[, start[, end]]) -> int
 |
 |      Return the lowest index in S where substring sub is found,
 |      such that sub is contained within S[start:end].  Optional
 |      arguments start and end are interpreted as in slice notation.
 |
 |      Return -1 on failure.
 |
 |  format(...)
 |      S.format(*args, **kwargs) -> str
 |
 |      Return a formatted version of S, using substitutions from args and kwargs.
 |      The substitutions are identified by braces ('{' and '}').
 |
 |  format_map(...)
 |      S.format_map(mapping) -> str
 |
 |      Return a formatted version of S, using substitutions from mapping.
 |      The substitutions are identified by braces ('{' and '}').
 |
 |  index(...)
 |      S.index(sub[, start[, end]]) -> int
 |
 |      Return the lowest index in S where substring sub is found,
 |      such that sub is contained within S[start:end].  Optional
 |      arguments start and end are interpreted as in slice notation.
 |
 |      Raises ValueError when the substring is not found.
 |
 |  isalnum(self, /)
 |      Return True if the string is an alpha-numeric string, False otherwise.
 |
 |      A string is alpha-numeric if all characters in the string are alpha-numeric and
 |      there is at least one character in the string.
 |
 |  isalpha(self, /)
 |      Return True if the string is an alphabetic string, False otherwise.
 |
 |      A string is alphabetic if all characters in the string are alphabetic and there
 |      is at least one character in the string.
 |
 |  isascii(self, /)
 |      Return True if all characters in the string are ASCII, False otherwise.
 |
 |      ASCII characters have code points in the range U+0000-U+007F.
 |      Empty string is ASCII too.
 |
 |  isdecimal(self, /)
 |      Return True if the string is a decimal string, False otherwise.
 |
 |      A string is a decimal string if all characters in the string are decimal and
 |      there is at least one character in the string.
 |
 |  isdigit(self, /)
 |      Return True if the string is a digit string, False otherwise.
 |
 |      A string is a digit string if all characters in the string are digits and there
 |      is at least one character in the string.
 |
 |  isidentifier(self, /)
 |      Return True if the string is a valid Python identifier, False otherwise.
 |
 |      Call keyword.iskeyword(s) to test whether string s is a reserved identifier,
 |      such as "def" or "class".
 |
 |  islower(self, /)
 |      Return True if the string is a lowercase string, False otherwise.
 |
 |      A string is lowercase if all cased characters in the string are lowercase and
 |      there is at least one cased character in the string.
 |
 |  isnumeric(self, /)
 |      Return True if the string is a numeric string, False otherwise.
 |
 |      A string is numeric if all characters in the string are numeric and there is at
 |      least one character in the string.
 |
 |  isprintable(self, /)
 |      Return True if the string is printable, False otherwise.
 |
 |      A string is printable if all of its characters are considered printable in
 |      repr() or if it is empty.
 |
 |  isspace(self, /)
 |      Return True if the string is a whitespace string, False otherwise.
 |
 |      A string is whitespace if all characters in the string are whitespace and there
 |      is at least one character in the string.
 |
 |  istitle(self, /)
 |      Return True if the string is a title-cased string, False otherwise.
 |
 |      In a title-cased string, upper- and title-case characters may only
 |      follow uncased characters and lowercase characters only cased ones.
 |
 |  isupper(self, /)
 |      Return True if the string is an uppercase string, False otherwise.
 |
 |      A string is uppercase if all cased characters in the string are uppercase and
 |      there is at least one cased character in the string.
 |
 |  join(self, iterable, /)
 |      Concatenate any number of strings.
 |
 |      The string whose method is called is inserted in between each given string.
 |      The result is returned as a new string.
 |
 |      Example: '.'.join(['ab', 'pq', 'rs']) -> 'ab.pq.rs'
 |
 |  ljust(self, width, fillchar=' ', /)
 |      Return a left-justified string of length width.
 |
 |      Padding is done using the specified fill character (default is a space).
 |
 |  lower(self, /)
 |      Return a copy of the string converted to lowercase.
 |
 |  lstrip(self, chars=None, /)
 |      Return a copy of the string with leading whitespace removed.
 |
 |      If chars is given and not None, remove characters in chars instead.
 |
 |  partition(self, sep, /)
 |      Partition the string into three parts using the given separator.
 |
 |      This will search for the separator in the string.  If the separator is found,
 |      returns a 3-tuple containing the part before the separator, the separator
 |      itself, and the part after it.
 |
 |      If the separator is not found, returns a 3-tuple containing the original string
 |      and two empty strings.
 |
 |  removeprefix(self, prefix, /)
 |      Return a str with the given prefix string removed if present.
 |
 |      If the string starts with the prefix string, return string[len(prefix):].
 |      Otherwise, return a copy of the original string.
 |
 |  removesuffix(self, suffix, /)
 |      Return a str with the given suffix string removed if present.
 |
 |      If the string ends with the suffix string and that suffix is not empty,
 |      return string[:-len(suffix)]. Otherwise, return a copy of the original
 |      string.
 |
 |  replace(self, old, new, count=-1, /)
 |      Return a copy with all occurrences of substring old replaced by new.
 |
 |        count
 |          Maximum number of occurrences to replace.
 |          -1 (the default value) means replace all occurrences.
 |
 |      If the optional argument count is given, only the first count occurrences are
 |      replaced.
 |
 |  rfind(...)
 |      S.rfind(sub[, start[, end]]) -> int
 |
 |      Return the highest index in S where substring sub is found,
 |      such that sub is contained within S[start:end].  Optional
 |      arguments start and end are interpreted as in slice notation.
 |
 |      Return -1 on failure.
 |
 |  rindex(...)
 |      S.rindex(sub[, start[, end]]) -> int
 |
 |      Return the highest index in S where substring sub is found,
 |      such that sub is contained within S[start:end].  Optional
 |      arguments start and end are interpreted as in slice notation.
 |
 |      Raises ValueError when the substring is not found.
 |
 |  rjust(self, width, fillchar=' ', /)
 |      Return a right-justified string of length width.
 |
 |      Padding is done using the specified fill character (default is a space).
 |
 |  rpartition(self, sep, /)
 |      Partition the string into three parts using the given separator.
 |
 |      This will search for the separator in the string, starting at the end. If
 |      the separator is found, returns a 3-tuple containing the part before the
 |      separator, the separator itself, and the part after it.
 |
 |      If the separator is not found, returns a 3-tuple containing two empty strings
 |      and the original string.
 |
 |  rsplit(self, /, sep=None, maxsplit=-1)
 |      Return a list of the substrings in the string, using sep as the separator string.
 |
 |        sep
 |          The separator used to split the string.
 |
 |          When set to None (the default value), will split on any whitespace
 |          character (including n r t f and spaces) and will discard
 |          empty strings from the result.
 |        maxsplit
 |          Maximum number of splits (starting from the left).
 |          -1 (the default value) means no limit.
 |
 |      Splitting starts at the end of the string and works to the front.
 |
 |  rstrip(self, chars=None, /)
 |      Return a copy of the string with trailing whitespace removed.
 |
 |      If chars is given and not None, remove characters in chars instead.
 |
 |  split(self, /, sep=None, maxsplit=-1)
 |      Return a list of the substrings in the string, using sep as the separator string.
 |
 |        sep
 |          The separator used to split the string.
 |
 |          When set to None (the default value), will split on any whitespace
 |          character (including n r t f and spaces) and will discard
 |          empty strings from the result.
 |        maxsplit
 |          Maximum number of splits (starting from the left).
 |          -1 (the default value) means no limit.
 |
 |      Note, str.split() is mainly useful for data that has been intentionally
 |      delimited.  With natural text that includes punctuation, consider using
 |      the regular expression module.
 |
 |  splitlines(self, /, keepends=False)
 |      Return a list of the lines in the string, breaking at line boundaries.
 |
 |      Line breaks are not included in the resulting list unless keepends is given and
 |      true.
 |
 |  startswith(...)
 |      S.startswith(prefix[, start[, end]]) -> bool
 |
 |      Return True if S starts with the specified prefix, False otherwise.
 |      With optional start, test S beginning at that position.
 |      With optional end, stop comparing S at that position.
 |      prefix can also be a tuple of strings to try.
 |
 |  strip(self, chars=None, /)
 |      Return a copy of the string with leading and trailing whitespace removed.
 |
 |      If chars is given and not None, remove characters in chars instead.
 |
 |  swapcase(self, /)
 |      Convert uppercase characters to lowercase and lowercase characters to uppercase.
 |
 |  title(self, /)
 |      Return a version of the string where each word is titlecased.
 |
 |      More specifically, words start with uppercased characters and all remaining
 |      cased characters have lower case.
 |
 |  translate(self, table, /)
 |      Replace each character in the string using the given translation table.
 |
 |        table
 |          Translation table, which must be a mapping of Unicode ordinals to
 |          Unicode ordinals, strings, or None.
 |
 |      The table must implement lookup/indexing via __getitem__, for instance a
 |      dictionary or list.  If this operation raises LookupError, the character is
 |      left untouched.  Characters mapped to None are deleted.
 |
 |  upper(self, /)
 |      Return a copy of the string converted to uppercase.
 |
 |  zfill(self, width, /)
 |      Pad a numeric string with zeros on the left, to fill a field of the given width.
 |
 |      The string is never truncated.
 |
 |  ----------------------------------------------------------------------
 |  Static methods defined here:
 |
 |  __new__(*args, **kwargs) from builtins.type
 |      Create and return a new object.  See help(type) for accurate signature.
 |
 |  maketrans(...)
 |      Return a translation table usable for str.translate().
 |
 |      If there is only one argument, it must be a dictionary mapping Unicode
 |      ordinals (integers) or characters to Unicode ordinals, strings or None.
 |      Character keys will be then converted to ordinals.
 |      If there are two arguments, they must be strings of equal length, and
 |      in the resulting dictionary, each character in x will be mapped to the
 |      character at the same position in y. If there is a third argument, it
 |      must be a string, whose characters will be mapped to None in the result.

Tipos contenedores

En Python existen tipos compuestos (que pueden contener más de un valor). Uno de ellos que ya vimos es el tipo string que es una cadena de caracteres. Veamos otros:

Listas

Las listas son tipos compuestos. Se definen separando los elementos con comas, todos encerrados entre corchetes. En general las listas pueden contener diferentes tipos, y pueden no ser todos iguales, pero suelen utilizarse con ítems del mismo tipo. Algunas características:

  • Los elementos no son necesariamente homogéneos en tipo.

  • Los elementos están ordenados.

  • Se accede mediante un índice.

  • Están definidas operaciones entre Listas, así como algunos métodos

    • x in L (¿x es un elemento de L?)

    • x not in L (¿x no es un elemento de L?)

    • L1 + L2 (concatenar L1 y L2)

    • n*L1 (n veces L1)

    • L1*n (n veces L1)

    • L[i] (Elemento i-ésimo)

    • L[i:j] (Elementos i a j)

    • L[i:j:k] (Elementos i a j, elegidos uno de cada k)

    • len(L) (longitud de L)

    • min(L) (Mínimo de L)

    • max(L) (Máximo de L)

    • L.index(x, [i]) (Índice de x, iniciando en i)

    • L.count(x) (Número de veces que aparece x en L)

    • L.append(x) (Agrega el elemento x al final)

Veamos algunos ejemplos:

cuadrados = [1, 9, 16, 25]

En esta línea hemos declarado una variable llamada cuadrados, y le hemos asignado una lista de cuatro elementos. En algunos aspectos las listas son muy similares a los strings. Se pueden realizar muchas de las mismas operaciones en strings, listas y otros objetos sobre los que se pueden iterar (iterables).

Las listas pueden accederse por posición y también pueden rebanarse (slicing)

Nota

La indexación de iteradores empieza desde cero (como en C)

cuadrados[0]
1
cuadrados[3]
25
cuadrados[-1]
25
cuadrados[:3:2]
[1, 16]
cuadrados[-2:]
[16, 25]

Los índices pueden ser positivos (empezando desde cero) o negativos empezando desde -1.

cuadrados:

1

9

16

25

índices:

0

1

2

3

índices negativos:

-4

-3

-2

-1

Nota

La asignación entre listas no copia todos los datos

a = cuadrados
a is cuadrados
True
print("Valores originales")
print(a)
cuadrados[0]= -1
print("Valores modificados")
print(a)
print(cuadrados)
Valores originales
[1, 9, 16, 25]
Valores modificados
[-1, 9, 16, 25]
[-1, 9, 16, 25]
a is cuadrados
True
cuadrados[0] = 1
b = cuadrados.copy()
print("Valores originales")
print(b)
print(cuadrados)
print("Valores modificados")
cuadrados[0]=-2
print(b)
print(cuadrados)
Valores originales
[1, 9, 16, 25]
[1, 9, 16, 25]
Valores modificados
[1, 9, 16, 25]
[-2, 9, 16, 25]

Comprensión de Listas

Una manera sencilla de definir una lista es utilizando algo que se llama Comprensión de listas. Como primer ejemplo veamos una lista de números cuadrados como la que escribimos anteriormente. En lenguaje matemático la defiríamos como \(S = \{x^{2} : x \in \{0 \dots 9\}\}\). En python es muy parecido.

Podemos crear la lista cuadrados utilizando compresiones de listas

L1 = [1,3,5]
L2= [i**2 for i in L1]
print(L2)
[1, 9, 25]
cuadrados = [i**2 for i in range(10)]
cuadrados
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

Una lista con los cuadrados sólo de los números pares también puede crearse de esta manera, ya que puede incorporarse una condición:

L = [a**2 for a in range(2,21) if a % 2 == 0]
L
[4, 16, 36, 64, 100, 144, 196, 256, 324, 400]

Tuplas

Las tuplas son objetos similares a las listas, sobre las que se puede iterar y seleccionar partes según su índice. La principal diferencia es que son inmutables mientras que las listas pueden modificarse.

L1 = [0,1,2,3,4,5] # Las listas se definen con corchetes
T1 = (0,1,2,3,4,5) # Las tuplas se definen con paréntesis
L1[0] = -1
print(f"L1[0] = {L1[0]}")
L1[0] = -1
try:
    T1[0] = -1
    print(f"{T1[0] = }")
except:
    print('Tuples son inmutables')
Tuples son inmutables

Las tuplas se usan cuando uno quiere crear una “variable” que no va a ser modificada. Además códigos similares con tuplas pueden ser un poco más rápidos que si usan listas.

Un uso común de las tuplas es el de asignación simultánea a múltiples variables:

a, b, c = (1, 3, 5)
print(b)
print(a, b, c)
3
1 3 5
# Los paréntesis son opcionales en este caso
a, b, c = 4, 5, 6
print(b)
print(a,b,c)
5
4 5 6

Un uso muy común es el de intercambiar el valor de dos variables

print(a,b)
a, b = b, a                     # swap
print(a,b)
4 5
5 4

Rangos

Los objetos de tipo range representan una secuencia inmutable de números y se usan habitualmente para ejecutar un bucle for un número determinado de veces. El formato es uno de:

range(stop)
range(start, stop)
range(start, stop, step)
range(2)
range(0, 2)
type(range(2))
range
range(2,9)
range(2, 9)
list(range(2,9))
[2, 3, 4, 5, 6, 7, 8]
list(range(2,9,2))
[2, 4, 6, 8]

Operaciones sobre listas

Veamos algunas operaciones que se pueden realizar sobre listas. Por ejemplo, se puede fácilmente:

  • concatenar dos listas,

  • buscar un valor dado,

  • agregar elementos,

  • borrar elementos,

  • calcular su longitud,

  • invertirla

Empecemos concatenando dos listas, usando el operador “suma”

L1 = [0,1,2,3,4,5]
L1 + L1
[0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5]
2*L1 == L1 + L1
True
L = 3*L1

Las listas tienen definidos métodos, que podemos ver con la ayuda incluida, por ejemplo haciendo help(list)

print(L)
[0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5]
L.index(3)                      # Índice del elemento de valor 3
3
L.index(3,4)                    # Índice del valor 3, empezando del cuarto
9
L.count(3)                      # Cuenta las veces que aparece el valor "3"
3

Si queremos agregar un elemento al final utilizamos el método append:

L.append(8)
print(L)
[0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 8]
L.append([9, 8, 7])
print(L)
[0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 8, [9, 8, 7]]

Si queremos insertar un elemento en una posición que no es el final de la lista, usamos el método insert(). Por ejemplo para insertar el valor 6 en la primera posición:

L.insert(0,6)
print(L)
[6, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 8, [9, 8, 7]]
L.insert(-2,6)
print(L)
[6, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 8, [9, 8, 7]]

En las listas podemos sobreescribir uno o más elementos

L[0:3] = [2,3,4]
L[4]=-4
print(L)
[2, 3, 4, 2, -4, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 8, [9, 8, 7]]
L[-2:]=[0,1]
print(L)
[2, 3, 4, 2, -4, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 1]
L[-2:] = [7,"fin2"]
print(L)
[2, 3, 4, 2, -4, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 7, 'fin2']
L.extend([0,1])                 # Extendemos con varios elementos
print(L)
[2, 3, 4, 2, -4, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 7, 'fin2', 0, 1]
print(L)
L.remove('fin2')                     # Remueve la primera aparición del valor 3
print(L)
[2, 3, 4, 2, -4, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 7, 'fin2', 0, 1]
[2, 3, 4, 2, -4, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1]
print(L1)
L1.reverse()
print(L1)
[0, 1, 2, 3, 4, 5]
[5, 4, 3, 2, 1, 0]

Función de Python que invierte una lista

print(list(reversed(L1)))
[0, 1, 2, 3, 4, 5]
L.sort()          # Ordena la lista (si los elementos son comparables)
print(L)
[-4, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 6, 7]

El método sort() de las listas acepta dos argumentos opcionales: key y reverse

L.sort(True)
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

Cell In[50], line 1
----> 1 L.sort(True)


TypeError: sort() takes no positional arguments
L.sort(reverse=True)
print(L)
[7, 6, 5, 5, 5, 4, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 0, 0, 0, -4]

Funciones que aplican sobre listas

Hay algunas funciones de Python que se aplican sobre listas (o sobre iterables en general). Algunas de ellas son la suma sum() e inversión reversed()

L
[7, 6, 5, 5, 5, 4, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 0, 0, 0, -4]
sum(L)
60
reversed(L)
<list_reverseiterator at 0x7fed3814ceb0>
L1 = list(reversed(L))
print(L1)
[-4, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 6, 7]

Las funciones mínimo min(), máximo max() y ordenar sorted() toman como argumento una lista (u otro iterable) de elementos que pueden compararse entre sí

print(min(L), max(L))
-4 7
print(sorted(L))
[-4, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 6, 7]
help(sorted)
Help on built-in function sorted in module builtins:

sorted(iterable, /, *, key=None, reverse=False)
    Return a new list containing all items from the iterable in ascending order.

    A custom key function can be supplied to customize the sort order, and the
    reverse flag can be set to request the result in descending order.

Estas funciones toman además un argumento opcional key, que es una función que se aplica a cada elemento antes de compararlos

Puede encontrarse más información en la Biblioteca de Python.

s = "abcde"
L3 = ['hola','que','tal']
s.join(L3)
'holaabcdequeabcdetal'
" ".join(L3)
'hola que tal'
print("\n".join(L3))
hola
que
tal

Ejercicios 02 (c)

  1. Para Entregar: Manejos de listas:

    • Cree la lista N de longitud 50, donde cada elemento es un número entero de 1 a 50 inclusive (Ayuda: vea la expresión range).

    • Invierta la lista.

    • Extraiga de N una lista N1 que contenga sólo aquellos elementos que sean el cuadrado de algún número entero.

    • Extraiga de N una lista N2 que contenga sólo aquellos elementos que sean iguales al \(n^2-n\) para algún número entero \(n\).

    Ayuda: Puede resultar útil recordar el uso de comprensión de listas.

    Debe enviar por correo electrónico, con asunto “02_Suapellido”, un programa llamado 02_SuApellido.py (en todos los casos utilice su apellido, no la palabra “SuApellido”).

  2. Cree una lista de la forma L = [1,3,5,...,17,19,19,17,...,3,1] (Ayuda: vea la expresión range).

  3. Escriba una función que tome un número entero de tres cifras, y devuelva el mayor entero que se puede formar con esas cifras (Ayuda: considere convertir el número entero a otros tipos).

  4. Construya una lista L2 con 2000 elementos, todos iguales a 0.0005. Imprima su suma utilizando la función sum y comparar con el resultado que arroja la función que existe en el módulo math para realizar suma de números de punto flotante.

  5. Operación “rara” sobre una lista:

    • Defina la lista L = [0,1]

    • Realice la operación L.append(L)

    • Ahora imprima L, e imprima el último elemento de L.

    • Haga que una nueva lista L1 tenga el valor del último elemento de L y repita el inciso anterior.


.