Aparte de los tipos numéricos, hay en Python otros tipos compuestos, como ser secuencias, sets y mapeos.
Dentro de las secuencias, ya vimos las cadenas de caracteres (strings).
Otro tipo muy importante de secuencia son las listas.
Una lista en Python es una estructura de datos formada por una secuencia ordenada de objetos.
Una forma básica de definirlas es entre corchetes, separando sus elementos con comas.
lista_1 = [17, "hola", [23, 12], 'foo']
Las listas en Python son:
Los elementos de una lista pueden accederse mediante su índice, siendo 0 el índice del primer elemento.
lista_1[0]
La función len() devuelve la longitud de la lista (su cantidad de elementos).
len(lista_1)
Los índices de una lista van entonces de 0 a len(lista) - 1
lista_1[3]
Pueden usarse también índices negativos, siendo -1 el índice del último elemento.
lista_1[-1]
Los índices negativos van entonces de -1 (último elemento) a -len(lista) (primer elemento).
lista_1[-len(lista_1)]
A través de los índices, pueden cambiarse los elementos de una lista en el lugar.
lista_1[1] = "adiós"
lista_1
La programación estructurada es un paradigma de programación basado en utilizar funciones o subrutinas, y únicamente tres estructuras de control:
La programación estructurada se fundamente en el teorema correspondiente, que establece que toda función computable puede ser implementada en un lenguaje de programación que combine sólo estas tres estructuras lógicas o de control.
La estructura de secuencia es la que se da naturalmente en el lenguaje, ya que por defecto las sentencias son ejecutadas en el orden en que aparecen escritas en el programa.
Para las estructuras condicionales o de selección, Python dispone de la instrucción if, que puede combinarse con instrucciones elif y/o else.
Para los bucles o iteraciones existen las estructuras while y for.
La instrucción if verifica el valor de verdad de una expresión, y si es verdadera ejecuta el código correspondiente.
La sintaxis es:
if condición:
bloque de código (indentado)
La condición debe ser cualquier expresión que devuelva el valor True o False.
Por ejemplo, pueden usarse cualquiera de los operadores de comparación vistos en la clase 1.
a = 5
if a > 0:
print("a es positivo")
Las comparaciones pueden combinarse con los operadores booleanos and, or y not.
a = 5
if a >= 0 and a < 10:
print("a es un número entre 0 y 9")
Vamos a definir una función que, dada una altura en número de nota MIDI, verfica que se encuentra dentro de un rango determinado (por defecto, el rango completo de notas MIDI, 0 a 127).
def nota_en_rango(nota, lim_inf=0, lim_sup=127):
"""Verifica si una altura en nota MIDI está dentro de un rango"""
if nota < lim_inf or nota > lim_sup: # imprime una advertencia si la nota está fuera de rango.
print("ATENCIÓN: la nota {} está fuera del rango {} - {}".format(nota, lim_inf, lim_sup))
nota = 88
nota_en_rango(nota)
nota_en_rango(nota, 55, 80)
La instrucción if puede opcionalmente combinarse con la instrucción else, que ejecuta un bloque de código alternativo, cuando no se cumple la condición del if.
Por ejemplo, la función anterior solamente imprime una advertencia cuando la altura está fuera de rango; en caso contrario, pasa silenciosamente. Podemos completar la estructura if con un else, para que la función reporte un resultado en todos los casos.
def nota_en_rango(nota, lim_inf=0, lim_sup=127):
"""Verifica si una altura en nota MIDI está dentro de un rango"""
if nota < lim_inf or nota > lim_sup: # imprime una advertencia si la nota está fuera de rango.
print("ATENCIÓN: la nota {} está fuera del rango {} - {}".format(nota, lim_inf, lim_sup))
else: # en caso contrario, devuelve un OK
print("nota {}: OK".format(nota))
nota = 88
nota_en_rango(nota)
nota_en_rango(nota, 55, 80)
Las estructuras condicionales if también pueden combinarse con una o más instrucciones elif, que es una abreviación de else, if.
Cada elif agrega una nueva condición a probar, si no se cumple la condición del if o elif anterior.
La función del ejemplo anterior se puede ampliar para que primero chequee si la nota está por debajo del límite inferior, y en caso contrario, ver si excede el límite superior. De no cumplirse ninguna de las dos condiciones, se ejecuta el else.
def nota_en_rango(nota, lim_inf=0, lim_sup=127):
"""Verifica si una altura en nota MIDI está dentro de un rango"""
if nota < lim_inf: # imprime una advertencia si está debajo del límite inferior
print("ATENCIÓN: la nota {} está por debajo del límite inferior".format(nota))
elif nota > lim_sup: # imprime una advertencia si encima del límite superior
print("ATENCIÓN: la nota {} está por encima del límite superior".format(nota))
else: # en caso contrario, devuelve un OK
print("nota {}: OK".format(nota))
nota1 = 88
nota2 = -3
nota3 = 132
nota_en_rango(nota1)
nota_en_rango(nota2)
nota_en_rango(nota3)
El esquema de una estructura completa con un if, uno o más elif, y un else, sería la siguiente:
if condición1:
bloque de código 1 (indentado)
elif condición2:
bloque de código 2 (indentado)
·
·
·
else:
bloque de código N (indentado)
La instrucción while permite implementar un ciclo o bucle: verifica el valor de una condición, y si ésta es verdadera, ejecuta el código que sigue. El proceso se repite hasta que la expresión condicional sea falsa.
El esquema de la sintaxis es:
while condición:
bloque de código (indentado)
contador = 0
while contador <= 5:
print(contador, end=' ')
contador +=1 # se incrementa el valor de la variable
Es importante asegurarse que en algún momento la expresión condicional se vuelva falsa, de lo contrario el programa quedará estancado en un bucle sin fin. En el ejemplo anterior tomamos esa precaución, incrementado el valor de la variable contador en cada pasada.
Es frecuente que una variable tenga que ser redefinida en función de sí misma, como en el ejemplo anterior, donde a la variable contador se le sumaba 1 en cada pasada. En vez de escribir
contador = contador + 1
se puede abreviar a su equivalente
contador += 1
que no sólo es más corto de escribir, sino también más eficiente.
Existe en Python todo un conjunto de operadores de este tipo, llamados de asignación aumentada, entre los que podemos mencionar:
X += Y ( X = X + Y ) X −= Y ( X = X - Y ) X *= Y ( X = X * Y ) X **= Y ( X = X ** Y ) X /= Y ( X = X / Y ) X //= Y ( X = X // Y ) X %= Y ( X = X % Y )
Al igual que la estructura if, la estructura while también puede combinarse con una instrucción else. El bloque de código a continuación de la instrucción else se ejecutará cuando la expresión condicional del while sea falsa.
El nombre de la instrucción es equívoco, ya que el bloque del else se ejecutará en todos los casos; tiene la ventaja de mantener el mismo nombre y la misma sintaxis que en las demás estructuras de control.
En el ejemplo anterior podemos agregar una instrucción else al final, que ejecutará el código siguiente cuando la condición del while sea falsa.
contador = 0
while contador <= 5:
print(contador, end=' ')
contador +=1 # se incrementa el valor de la variable
else:
print("\nno se ejecuta el while, el contador es", contador)
def fib(n):
"""Imprime una serie de Fibonacci hasta el número n."""
a, b = 0, 1
while a < n:
print(a, end=' ')
a, b = b, a+b
print() # imprime un salto de línea cuando termina
fib(1000)
La instrucción for implementa un bucle, recorriendo ordenadamente una secuencia, o cualquier otro objeto iterable.
La sintaxis básica es la siguiente:
for i in s:
bloque de código
for item in [9, 7, 13, 22]:
print(item)
for letra in "hola":
print(letra*5, end='')
Al igual que en las estructuras de bucle creadas con la instrucción while, acá se puede utilizar la instrucción else para ejecutar un bloque de código una vez que se haya terminado la iteración.
frutas_en_la_heladera = ['una manzana', 'dos naranjas', 'un durazno']
for i in frutas_en_la_heladera:
print("como", i)
else:
print("se terminaron las frutas...")
En las estructuras for es frecuente utilizar la función range(), que genera una secuencia de valores enteros entre un valor inicial y un límite superior (sin uncluirlo), con un determinado incremento.
Su sintaxis completa es:
range(valor_inicial, limite_superior, incremento)
Por lo tanto, range(10) equivale a range(0, 10, 1).
for i in range(5): # de 0 a 5 (excluyente), con incremento 1
print(i, end=' ')
for i in range(5,10): # de 5 a 10 (excluyente), con incremento 1
print(i, end=' ')
for i in range(0,20,5): # de 0 a 20 (excluyente), con incremento 5
print(i, end=' ')
Aunque tiene la forma de una función, list() es un constructor, que crea una lista a partir de un objeto iterable.
Si el objeto ya es una lista, simplemente se crea una copia.
Pero puede ser otro tipo de secuencia, como una cadena str, o una secuencia generada por la función range().
b = list("¡hola!")
print(b)
a = list(range(5, -5, -1))
print(a)
Ampliar el programa del Ejercicio 1.1 (clase 1), de modo de que calcule el factor de multiplicación y la frecuencia resultante para todos los grados de la escala.
Para cada grado se debe imprimir en pantalla:
Las tres columnas deben estar alineadas por tabuladores.
Ejemplo de ejecución del programa, para división en 12 de la octava, frecuencia de referencia 440:
ingrese la cantidad de grados a dividir la "octava": 12 ingrese la relación de frecuencia correspondiente a la "octava": 2 ingrese la frecuencia base en Hz: 440 cociente: 1.0594630943592953 0 1.0000 440.00 1 1.0595 466.16 2 1.1225 493.88 3 1.1892 523.25 4 1.2599 554.37 5 1.3348 587.33 6 1.4142 622.25 7 1.4983 659.26 8 1.5874 698.46 9 1.6818 739.99 10 1.7818 783.99 11 1.8877 830.61 12 2.0000 880.00
Escribir un programa que, partiendo del armónico 8, calcule el factor de multiplicación hasta el armónico 16.
El programa debe preguntar una frecuencia de referencia (que se asociará al armónico 8), y para cada armónico se debe imprimir en pantalla:
Las tres columnas deben estar alineadas por tabuladores.
Ejemplo de ejecución del programa, para frecuencia de referencia 440:
ingrese la frecuencia base en Hz: 440 8 1.000 440.0 9 1.125 495.0 10 1.250 550.0 11 1.375 605.0 12 1.500 660.0 13 1.625 715.0 14 1.750 770.0 15 1.875 825.0 16 2.000 880.0