Tutorial Es Program Ac I On Ya Python

Descargar como pdf o txt
Descargar como pdf o txt
Está en la página 1de 685

1 - Objetivos del tutorial de Python

Este curso esta pensado para ser cursado por una persona que no conoce
nada de programación y se emplea el lenguaje Python como primer lenguaje
para acercarse a la programación de computadoras.
El objetivo fundamental de este tutorial es permitir que el estudiante pueda
resolver problemas de distinta índole (matemáticos, administrativos, juegos,
contables etc.) empleando como herramienta la computadora.
Hay que tener en cuenta que para llegar a ser un programador se debe
recorrer un largo camino donde cada tema es fundamental para conceptos
futuros. Es importante no dejar temas sin entender y relacionar.
La programación a diferencia de otras materias que ha estudiado como podría
ser la historia requiere un estudio metódico y ordenado (en historia se puede
estudiar la edad media sin tener grandes conocimientos de la edad antigua,
esto no pasa con el aprendizaje de la programación)
La programación es una actividad nueva para el estudiante, no hay en los
estudios primarios y secundarios una materia parecida.
Es bueno tenerse paciencia cuando los problemas no se resuelven por
completo, pero es de fundamental importancia dedicar tiempo al análisis
individual de los problemas.

¿Qué es un programa?
Programa: Conjunto de instrucciones que entiende una computadora para
realizar una actividad.
Todo programa tiene un objetivo bien definido: un procesador de texto es un
programa que permite cargar, modificar e imprimir textos, un programa de
ajedrez permite jugar al ajedrez contra el ordenador u otro contrincante
humano.
La actividad fundamental del programador es resolver problemas empleando el
ordenador como herramienta fundamental.
Para la resolución de un problema hay que plantear un algoritmo.
Algoritmo: Son los pasos a seguir para resolver un problema.

Diagrama de flujo
Un diagrama de flujo es la representación gráfica de un ALGORITMO.
Los símbolos gráficos principales a utilizar para el planteo de diagramas de
flujo son:
Estos son los elementos gráficos esenciales para el desarrollo de un diagrama
de flujo.

Planteo de un problema utilizando un


diagrama de flujo.
Para plantear un diagrama de flujo debemos tener muy en claro el problema a
resolver.
Ejemplo : Calcular el sueldo mensual de un operario conociendo la cantidad de
horas trabajadas y el pago por hora.
Podemos identificar:
Datos conocidos:
Horas trabajadas en el mes.
Pago por hora.
Proceso:
Cálculo del sueldo multiplicando la cantidad de horas por el pago por hora.
Información resultante:
Sueldo mensual.
Si hacemos un análisis todo problema está constituido por:
- Datos conocidos: Datos con los que se cuenta al plantear el problema.
- Proceso: Operaciones a realizar con los datos conocidos.
- Información resultante: Es la información que se obtiene del proceso y nos
permite resolver el problema.
Esta forma de expresar un problema identificando sus datos conocidos,
procesos e información resultante puede llegar a ser engorrosa para problemas
complejos donde hay muchos datos conocidos y procesos. Es por eso que
resulta mucho más efectivo representar los pasos para la resolución del
problema mediante un diagrama de flujo.

Resulta mucho más fácil entender un gráfico que un texto.


El diagrama de flujo nos identifica claramente los datos de entrada,
operaciones y datos de salida.
En el ejemplo tenemos dos datos de entrada: horasTrabajadas y costoHora, a
las entradas las representamos con un paralelogramo y hacemos un
paralelogramo por cada dato de entrada.
La operación se representa con un rectángulo, debemos hacer un rectángulo
por cada operación. A la salida la representamos con la hoja rota.
El diagrama de flujo nos da una idea del orden de ejecución de las actividades
en el tiempo. Primero cargamos los datos de entrada, luego hacemos las
operaciones necesarias y por último mostramos los resultados.
Variable: Es un depósito donde hay un valor. Consta de un nombre y
pertenece a un tipo de dato.
Para el ejemplo planteado la variable horasTrabajadas almacena la cantidad
de horas trabajadas por el operario. La variable valorHora almacena el precio
de una hora de trabajo. La variable sueldo almacena el sueldo a abonar al
operario.
En el ejemplo tenemos tres variables.
Tipos de variable.
Una variable puede almacenar:

- Valores Enteros (100, 260, etc.)


- Valores Reales (1.24, 2.90, 5.00, etc.)
- Cadenas de caracteres ("Juan", "Compras", "Listado", etc.)

Elección del nombre de una variable:


Debemos elegir nombres de variables representativas. En el ejemplo el nombre
horasTrabajadas es lo suficientemente claro para darnos una idea acabada
sobre su contenido. Podemos darle otros buenos nombres. Otros no son tan
representativos, por ejemplo hTr. Posiblemente cuando estemos resolviendo
un problema dicho nombre nos recuerde que almacenamos las horas
trabajadas por el operario pero cuando pase el tiempo y leamos el diagrama
probablemente no recordemos ni entendamos qué significa hTr.

Retornar

2 - Instalación del lenguaje y pasos


para crear nuestro primer programa
Ver videoPara la descarga del lenguaje Python lo hacemos del
sitio: python.org (descargar la versión más actual 3.8)
Ejecutamos el programa que descargamos y procedemos a instalarlo
(marcamos 'Add Python3.8 to PATH'):

Luego de haberse instalado podemos ejecutarlo desde el menú de opciones de


Windows:
Una vez que iniciamos el Python aparece la siguiente ventana:

Para crear nuestro primer programa debemos seleccionar desde el menú de


opciones "File"->"New File":
En esta nueva ventana debemos codificar nuestro programa en Python, el
programa mínimo es mostrar un mensaje por pantalla:

Procedemos a guardar en el "disco duro" el primer programa en Python


seleccionando la opción "File"->"Save", creamos un directorio donde
almacenaremos cada uno de nuestros ejercicio que desarrollaremos durante
este tutorial:
Para ejecutar el programa que codificamos debemos seleccionar desde la
ventana de nuestro editor la opción "Run" -> "Run Module":

Podemos ver en otra ventana el resultado de la ejecución de nuestro primer


programa en Python:
Acotaciones
Si el editor que viene por defecto con Python no le convence por ser muy
limitado y aplicado fundamentalmente en el aprendizaje de programación,
puede consultar otros editores disponibles para Python.
Mi recomendación es el editor VS Code.

Retornar

3 - Codificación del diagrama de flujo


en Python
El diagrama de flujo es nuestra herramienta para poder plantear una solución a
nuestro problema.
Para poder probar nuestra solución propuesta a un problema mediante un
diagrama de flujo lo debemos codificar seguidamente en Python.
Empezaremos con problemas muy sencillos y procederemos a implementar su
diagrama de flujo y seguidamente su codificación.

Problema
Hallar la superficie de un cuadrado conociendo el valor de un lado.
Diagrama de flujo:

Desde la ventana principal del entorno de Python procedemos a crear nuestro


segundo archivo "ejercicio2.py", lo grabamos como vimos en el concepto
anterior y codificamos en Python la siguiente solución al diagrama de flujo:
Ver video

lado=input("Ingrese la medida del lado del cuadra


do:")
lado=int(lado)
superficie=lado*lado
print("La superficie del cuadrado es")
print(superficie)
Si ejecutamos el programa "Run" -> "Run Module" podemos comprobar que se
solicita el ingreso por teclado de la medida del lado del cuadrado y
seguidamente nos muestra la superficie dependiendo del valor ingresado:
Para el ingreso de un dato por teclado y mostrar un mensaje se utiliza la
función input, esta función retorna todos los caracteres escritos por el operador
del programa:

lado=input("Ingrese la medida del lado del cuadrado:")

La variable lado guarda todos los caracteres ingresados pero no en formato


numérico, para esto debemos llamar a la función int:

lado=int(lado)

Ahora se vuelve a guardar en la variable lado el valor que ingresó el operador


pero en formato entero que posibilita hacer operaciones matemáticas con el
mismo.
Un formato simplificado para ingresar un valor entero por teclado y evitarnos
escribir las dos líneas anteriores es:

lado=int(input("Ingrese la medida del lado del cuadrado:"))

Procedemos a efectuar el cálculo de la superficie luego de ingresar el dato por


teclado y convertirlo a entero:

superficie=lado*lado
Para mostrar un mensaje por pantalla tenemos la función print que le pasamos
como parámetro una cadena de caracteres a mostrar que debe estar entre
simple o doble comillas:

print("La superficie del cuadrado es")

Para mostrar el contenido de la variable superficie no debemos encerrarla


entre comillas cuando llamamos a la función print:

print(superficie)

Algunas consideraciones
Python es sensible a mayúsculas y minúsculas, no es lo mismo llamar a la
función input con la sintaxis: Input.
Los nombres de variables también son sensibles a mayúsculas y minúsculas.
Son dos variables distintas si en un lugar iniciamos a la variable "superficie" y
luego hacemos referencia a "Superficie"
Los nombres de variable no pueden tener espacios en blanco, caracteres
especiales y empezar con un número.
Todo el código debe escribirse en la misma columna, estará incorrecto si
escribimos:

lado=input("Ingrese la medida del lado del cuadrado:")


lado=int(lado)
superficie=lado*lado
print("La superficie del cuadrado es")
print(superficie)

Hay más restricciones que iremos aprendiendo a medida que avance el curso.

Retornar

4 - Errores sintácticos y lógicos


Modificaremos el problema del concepto anterior y agregaremos adrede una
serie de errores tipográficos. Este tipo de errores siempre son detectados por el
intérprete de Python, antes de ejecutar el programa.
A los errores tipográficos, como por ejemplo indicar el nombre incorrecto de la
función, nombres de variables incorrectas, falta de paréntesis, palabras claves
mal escritas, etc. los llamamos errores SINTACTICOS.
Un programa no se puede ejecutar por completo sin corregir absolutamente
todos los errores sintácticos.
Existe otro tipo de errores llamados ERRORES LOGICOS. Este tipo de errores
en programas grandes (miles de líneas) son más difíciles de localizar. Por
ejemplo un programa que permite hacer la facturación pero la salida de datos
por impresora es incorrecta.

Problema
Hallar la superficie de un cuadrado conociendo el valor de un lado.
Diagrama de flujo:

Programa correctamente codificado:


Ver video
lado=int(input("Ingrese la medida del lado del cu
adrado:"))
superficie=lado*lado
print("La superficie del cuadrado es")
print(superficie)
Programa con un error sintáctico:

lado=int(input("Ingrese la medida del lado del cu


adrado:"))
superficie=lado*lado
print("La superficie del cuadrado es")
print(Superficie)
Es incorrecto la impresión de una variable nunca inicializada: "Superficie"
(debemos respetar como la iniciamos en las líneas anteriores)

Programa con un error lógico:

lado=int(input("Ingrese la medida del lado del cu


adrado:"))
superficie=lado*lado*lado
print("La superficie del cuadrado es")
print(superficie)
Como podemos observar si ejecutamos el programa no presenta ningún error
sintáctico, pero luego de ingresar el valor del lado del cuadrado (por ejemplo el
valor 10) obtenemos como resultado un valor incorrecto (imprime el 1000), esto
debido que definimos incorrectamente la fórmula para calcular la superficie del
cuadrado:

superficie=lado*lado*lado

Retornar

5 - Estructura de programación
secuencial
Cuando en un problema sólo participan operaciones, entradas y salidas se la
denomina una estructura secuencial.
Los problemas diagramados y codificados previamente emplean solo
estructuras secuenciales.
La programación requiere una práctica ininterrumpida de diagramación y
codificación de problemas.

Problema:
Realizar la carga de dos números enteros por teclado e imprimir su suma y su
producto.
Diagrama de flujo:

Tenemos dos entradas num1 y num2, dos operaciones: la suma y el producto


de los valores ingresados y dos salidas, que son los resultados de la suma y el
producto de los valores ingresados. En el símbolo de impresión podemos
indicar una o más salidas, eso queda a criterio del programador, lo mismo para
indicar las entradas por teclado.
Programa: ejercicio3.py
Ver video

num1=int(input("ingrese primer valor:"))


num2=int(input("ingrese segundo valor:"))
suma=num1+num2
producto=num1*num2
print("La suma de los dos valores es")
print(suma)
print("El producto de los dos valores es")
print(producto)

Problema:
Realizar la carga del precio de un producto y la cantidad a llevar. Mostrar
cuanto se debe pagar (se ingresa un valor entero en el precio del producto)
Diagrama de flujo:

Tenemos dos entradas: precio y cantidad, una operación para calcular el


importe y una salida.
Programa: ejercicio4.py
Ver video

precio=int(input("Ingrese el precio del producto:


"))
cantidad=int(input("Ingrese la cantidad de produc
tos a llevar:"))
importe=precio*cantidad
print("El importe a pagar es")
print(importe)
Problemas propuestos
• Realizar la carga del lado de un cuadrado, mostrar por pantalla el
perímetro del mismo (El perímetro de un cuadrado se calcula
multiplicando el valor del lado por cuatro)

Ver video

• Escribir un programa en el cual se ingresen cuatro números, calcular e


informar la suma de los dos primeros y el producto del tercero y el
cuarto.

Ver video

• Realizar un programa que lea cuatro valores numéricos e informar su


suma y promedio.

Ver video

• Calcular el sueldo mensual de un operario conociendo la cantidad de


horas trabajadas y el valor por hora.

Ver video
Solución

Retornar

6 - Estructuras condicionales simples


y compuestas
No todos los problemas pueden resolverse empleando estructuras
secuenciales. Cuando hay que tomar una decisión aparecen las estructuras
condicionales.
En nuestra vida diaria se nos presentan situaciones donde debemos decidir.
¿Elijo la carrera A o la carrera B?
¿Me pongo este pantalón?
Para ir al trabajo, ¿Elijo el camino A o el camino B?
Al cursar una carrera, ¿Elijo el turno mañana, tarde o noche?
Es común que en un problema se combinan estructuras secuenciales y
condicionales.

Estructura condicional simple.


Cuando se presenta la elección tenemos la opción de realizar una actividad o
no realizar ninguna.
Representación gráfica de una estructura condicional a utilizar en un diagrama
de flujo:

Podemos observar: El rombo representa la condición. Hay dos opciones que


se pueden tomar. Si la condición da verdadera se sigue el camino del
verdadero, o sea el de la derecha, si la condición da falsa se sigue el camino
de la izquierda donde no hay ninguna actividad.
Se trata de una estructura CONDICIONAL SIMPLE porque por el camino del
verdadero hay actividades y por el camino del falso no hay actividades.
Por el camino del verdadero pueden existir varias operaciones, entradas y
salidas, inclusive ya veremos que puede haber otras estructuras condicionales.

Problema:
Ingresar el sueldo de una persona, si supera los 3000 dolares mostrar un
mensaje en pantalla indicando que debe abonar impuestos.
Diagrama de flujo:

Podemos observar lo siguiente: Siempre se hace la carga del sueldo, pero si el


sueldo que ingresamos supera 3000 dolares se mostrará por pantalla el
mensaje "Esta persona debe abonar impuestos", en caso que la persona cobre
3000 o menos no aparece nada por pantalla.
Programa: ejercicio9.py
Ver video

sueldo=int(input("Ingrese cual es su sueldo:"))


if sueldo>3000:
print("Esta persona debe abonar impuestos")
La palabra clave "if" indica que estamos en presencia de una estructura
condicional; seguidamente disponemos la condición y finalizamos la línea con
el caracter dos puntos.
La actividad dentro del if se indenta generalmente a 4 espacios.
Todo lo que se encuentre en la rama del verdadero del if se debe disponer a 4
espacios corrido a derecha.
La indentación es una característica obligatoria del lenguaje Python para
codificación de las estructuras condicionales, de esta forma el intérprete de
Python puede identificar donde finalizan las instrucciones contenidas en la
rama verdadera del if.
Ejecutando el programa e ingresamos un sueldo superior a 3000. Podemos
observar como aparece en pantalla el mensaje "Esta persona debe abonar
impuestos", ya que la condición del if es verdadera:

Si lo volvemos a ejecutar e ingresamos un valor igual o inferior a 3000


podemos observar que la instrucción que se encuentra por la rama del
verdadero del if no se ejecuta:
Estructura condicional compuesta.
Cuando se presenta la elección tenemos la opción de realizar una actividad u
otra. Es decir tenemos actividades por el verdadero y por el falso de la
condición. Lo más importante que hay que tener en cuenta que se realizan las
actividades de la rama del verdadero o las del falso, NUNCA se realizan las
actividades de las dos ramas.
Representación gráfica:

En una estructura condicional compuesta tenemos actividades tanto por la


rama del verdadero como por la rama del falso.
Problema:
Realizar un programa que solicite ingresar dos números distintos y muestre por
pantalla el mayor de ellos.
Diagrama de flujo:

Se hace la entrada de num1 y num2 por teclado. Para saber cual variable tiene
un valor mayor preguntamos si el contenido de num1 es mayor (>) que el
contenido de num2, si la respuesta es verdadera vamos por la rama de la
derecha e imprimimos num1, en caso que la condición sea falsa vamos por la
rama de la izquierda (Falsa) e imprimimos num2.
Como podemos observar nunca se imprimen num1 y num2 simultáneamente.
Estamos en presencia de una ESTRUCTURA CONDICIONAL COMPUESTA
ya que tenemos actividades por la rama del verdadero y del falso.
Programa: ejercicio10.py
Ver video

num1=int(input("Ingrese primer valor:"))


num2=int(input("ingrese segundo valor:"))
print("El valor mayor es")
if num1>num2:
print(num1)
else:
print(num2)
Cotejemos el diagrama de flujo y la codificación y observemos que el primer
bloque después del if representa la rama del verdadero y el segundo bloque
después de la palabra clave else representa la rama del falso.
Ejecutamos el programa, si hubo errores sintácticos corrijamos y carguemos
dos valores, como por ejemplo:

Ingrese el primer valor: 10


Ingrese el segundo valor: 4
El valor mayor es
10

Si ingresamos los valores 10 y 4 la condición del if retorna verdadero y ejecuta


el primer bloque.
Un programa se controla y corrige probando todos sus posibles resultados.
Ejecutemos nuevamente el programa e ingresemos:

Ingrese el primer valor: 10


Ingrese el segundo valor: 54
El valor mayor es
54

Cuando a un programa le corregimos todos los errores sintácticos y lógicos ha


terminado nuestra tarea y podemos entregar el mismo al USUARIO que nos lo
solicitó.

Operadores
En una condición deben disponerse únicamente variables, valores constantes y
operadores relacionales.
Operadores Relacionales:

== Igualdad
!= Desigualdad

< menor

<= menor o igual

> mayor

>= mayor o igual

Operadores Matemáticos

+ suma
- resta
* multiplicación
/ división de flotantes
// división de enteros
% resto de una división
** exponenciación

Hay que tener en cuenta que al disponer una condición debemos seleccionar
que operador relacional se adapta a la pregunta.
Ejemplos:

Se ingresa un número multiplicarlo por 10 si es distinto a 0. (!=)


Se ingresan dos números mostrar una advertencia si son iguales. (==)

Los problemas que se pueden presentar son infinitos y la correcta elección del
operador solo se alcanza con la práctica intensiva en la resolución de
problemas.

Problemas propuestos
• Realizar un programa que solicite la carga por teclado de dos números,
si el primero es mayor al segundo informar su suma y diferencia, en caso
contrario informar el producto y la división del primero respecto al
segundo.
Ver video

• Se ingresan tres notas de un alumno, si el promedio es mayor o igual a


siete mostrar un mensaje "Promocionado".

Ver video

• Se ingresa por teclado un número positivo de uno o dos dígitos (1..99)


mostrar un mensaje indicando si el número tiene uno o dos dígitos.
(Tener en cuenta que condición debe cumplirse para tener dos dígitos un
número entero)

Ver video
Solución

Retornar

7 - Estructuras condicionales
anidadas
Estamos en presencia de una estructura condicional anidada cuando por la
rama del verdadero o el falso de una estructura condicional hay otra estructura
condicional.
El diagrama de flujo que se presenta contiene dos estructuras condicionales.
La principal se trata de una estructura condicional compuesta y la segunda es
una estructura condicional simple y está contenida por la rama del falso de la
primer estructura.
Es común que se presenten estructuras condicionales anidadas aún más
complejas.

Problema:
Confeccionar un programa que pida por teclado tres notas de un alumno,
calcule el promedio e imprima alguno de estos mensajes:
Si el promedio es >=7 mostrar "Promocionado".
Si el promedio es >=4 y <7 mostrar "Regular".
Si el promedio es <4 mostrar "Reprobado".
Diagrama de flujo:

Analicemos el siguiente diagrama. Se ingresan tres valores por teclado que


representan las notas de un alumno, se obtiene el promedio sumando los tres
valores y dividiendo por 3 dicho resultado (Tener en cuenta que el resultado es
un valor real ya que se utiliza el operador /).
Primeramente preguntamos si el promedio es superior o igual a 7, en caso
afirmativo va por la rama del verdadero de la estructura condicional mostramos
un mensaje que indica "Promocionado" (con comillas indicamos un texto que
debe imprimirse en pantalla).
En caso que la condición nos de falso, por la rama del falso aparece otra
estructura condicional, porque todavía debemos averiguar si el promedio del
alumno es superior o igual a cuatro o inferior a cuatro.
Estamos en presencia de dos estructuras condicionales compuestas.
Programa: ejercicio14.py
Ver video

nota1=int(input("Ingrese primer nota:"))


nota2=int(input("Ingrese segunda nota:"))
nota3=int(input("Ingrese tercer nota:"))
prom=(nota1+nota2+nota3)/3
if prom>=7:
print("Promocionado")
else:
if prom>=4:
print("Regular")
else:
print("Reprobado")
Codifiquemos y ejecutemos este programa. Al correr el programa deberá
solicitar por teclado la carga de tres notas y mostrarnos un mensaje según el
promedio de las mismas.
A la codificación del if anidado podemos observarla por el else del primer if.
Como vemos debemos indentar a 8 caracteres las ramas del verdadero y falso
del if anidado

Problemas propuestos
• Se cargan por teclado tres números distintos. Mostrar por pantalla el
mayor de ellos.

Ver video

• Se ingresa por teclado un valor entero, mostrar una leyenda que indique
si el número es positivo, negativo o nulo (es decir cero)

Ver video
• Confeccionar un programa que permita cargar un número entero positivo
de hasta tres cifras y muestre un mensaje indicando si tiene 1, 2, o 3
cifras. Mostrar un mensaje de error si el número de cifras es mayor.

Ver video

• Un postulante a un empleo, realiza un test de capacitación, se obtuvo la


siguiente información: cantidad total de preguntas que se le realizaron y
la cantidad de preguntas que contestó correctamente. Se pide
confeccionar un programa que ingrese los dos datos por teclado e
informe el nivel del mismo según el porcentaje de respuestas correctas
que ha obtenido, y sabiendo que:

• Nivel máximo: Porcentaje>=90%.

• Nivel medio: Porcentaje>=75% y <90%.

• Nivel regular: Porcentaje>=50% y <75%.

• Fuera de nivel: Porcentaje<50%.

Ver video
Solución

Retornar

8 - Condiciones compuestas con


operadores lógicos
Hasta ahora hemos visto los operadores:

relacionales (>, <, >=, <= , ==, !=)


matemáticos (+, -, *, /, //, **, %)

pero nos están faltando otros operadores imprescindibles:

lógicos (and y or)


Estos dos operadores se emplean fundamentalmente en las estructuras
condicionales para agrupar varias condiciones simples.

Operador and

Traducido se lo lee como “Y”. Si la Condición 1 es verdadera Y la condición 2


es verdadera luego ejecutar la rama del verdadero.
Cuando vinculamos dos condiciones con el operador “and”, las dos
condiciones deben ser verdaderas para que el resultado de la condición
compuesta de Verdadero y continúe por la rama del verdadero de la estructura
condicional.
La utilización de operadores lógicos permiten en muchos casos plantear
algoritmos más cortos y comprensibles.

Problema:
Confeccionar un programa que lea por teclado tres números enteros distintos y
nos muestre el mayor.
Diagrama de flujo:

Este ejercicio se puede resolver sin operadores lógicos pero el utilizarlos nos
permite que sea mas simple la solución.
La primera estructura condicional es una ESTRUCTURA CONDICIONAL
COMPUESTA con una CONDICION COMPUESTA.
Podemos leerla de la siguiente forma:
Si el contenido de la variable num1 es mayor al contenido de la variable num2
"Y" si el contenido de la variable num1 es mayor al contenido de la variable
num3 entonces la CONDICION COMPUESTA resulta Verdadera.
Si una de las condiciones simples da falso la CONDICION COMPUESTA da
Falso y continúa por la rama del falso.
Es decir que se mostrará el contenido de num1 si y sólo si num1 > num2 y
num1 > num3.
En caso de ser Falsa la condición, analizamos el contenido de num2 y num3
para ver cual tiene un valor mayor.
En esta segunda estructura condicional no se requieren operadores lógicos al
haber una condición simple.
Programa: ejercicio19.py
Ver video

num1=int(input("Ingrese primer valor:"))


num2=int(input("Ingrese segundo valor:"))
num3=int(input("Ingrese tercer valor:"))
print("El mayor de los tres valores es")
if num1>num2 and num1>num3:
print(num1)
else:
if num2>num3:
print(num2)
else:
print(num3)

Operador or

Traducido se lo lee como “O”. Si la condición 1 es Verdadera o la condición 2


es Verdadera, luego ejecutar la rama del Verdadero.
Cuando vinculamos dos o más condiciones con el operador “or", con que una
de las dos condiciones sea Verdadera alcanza para que el resultado de la
condición compuesta sea Verdadero.

Problema:
Se carga una fecha (día, mes y año) por teclado. Mostrar un mensaje si
corresponde al primer trimestre del año (enero, febrero o marzo) Cargar por
teclado el valor numérico del día, mes y año.
Ejemplo: dia:10 mes:2 año:2018
Diagrama de flujo:

La carga de una fecha se hace por partes, ingresamos las variables dia, mes y
año.
Mostramos el mensaje "Corresponde al primer trimestre" en caso que el mes
ingresado por teclado sea igual a 1, 2 ó 3.
En la condición no participan las variables dia y año.
Programa: ejercicio20.py
Ver video

dia=int(input("Ingrese nro de día:"))


mes=int(input("Ingrese nro de mes:"))
año=int(input("Ingrese nro de año:"))
if mes==1 or mes==2 or mes==3:
print("Corresponde al primer trimestre")

Problemas propuestos
• Realizar un programa que pida cargar una fecha cualquiera, luego
verificar si dicha fecha corresponde a Navidad.

Ver video

• Se ingresan por teclado tres números, si todos los valores ingresados


son menores a 10, imprimir en pantalla la leyenda "Todos los números
son menores a diez".

Ver video

• Se ingresan por teclado tres números, si al menos uno de los valores


ingresados es menor a 10, imprimir en pantalla la leyenda "Alguno de los
números es menor a diez".

Ver video

• Se ingresan tres valores por teclado, si todos son iguales se imprime la


suma del primero con el segundo y a este resultado se lo multiplica por
el tercero.

Ver video

• Escribir un programa que pida ingresar la coordenada de un punto en el


plano, es decir dos valores enteros x e y (distintos a cero).
Posteriormente imprimir en pantalla en que cuadrante se ubica dicho
punto. (1º Cuadrante si x > 0 Y y > 0 , 2º Cuadrante: x < 0 Y y > 0, etc.)

Ver video

• De un operario se conoce su sueldo y los años de antigüedad. Se pide


confeccionar un programa que lea los datos de entrada e informe:
a) Si el sueldo es inferior a 500 y su antigüedad es igual o superior a 10
años, otorgarle un aumento del 20 %, mostrar el sueldo a pagar.
b)Si el sueldo es inferior a 500 pero su antigüedad es menor a 10 años,
otorgarle un aumento de 5 %.
c) Si el sueldo es mayor o igual a 500 mostrar el sueldo en pantalla sin
cambios.

Ver video

• Escribir un programa en el cual: dada una lista de tres valores numéricos


distintos se calcule e informe su rango de variación (debe mostrar el
mayor y el menor de ellos)

Ver video
Solución

Retornar

9 - Estructura repetitiva while


Hasta ahora hemos empleado estructuras SECUENCIALES y
CONDICIONALES. Existe otro tipo de estructuras tan importantes como las
anteriores que son las estructuras REPETITIVAS.
Una estructura repetitiva permite ejecutar una instrucción o un conjunto de
instrucciones varias veces.
Una estructura repetitiva se caracteriza por:
- La sentencia o las sentencias que se repiten.
- El test o prueba de condición antes de cada repetición, que motivará que se
repitan o no las instrucciones.

Estructura repetitiva while.


Representación gráfica de la estructura while:
No debemos confundir la representación gráfica de la estructura repetitiva
while (Mientras) con la estructura condicional if (Si)
Funcionamiento: En primer lugar se verifica la condición, si la misma resulta
verdadera se ejecutan las operaciones que indicamos por la rama del
Verdadero.
A la rama del verdadero la graficamos en la parte inferior de la condición. Una
línea al final del bloque de repetición la conecta con la parte superior de la
estructura repetitiva.
En caso que la condición sea Falsa continúa por la rama del Falso y sale de la
estructura repetitiva para continuar con la ejecución del algoritmo.
El bloque se repite MIENTRAS la condición sea Verdadera.
Importante: Si la condición siempre retorna verdadero estamos en presencia
de un ciclo repetitivo infinito. Dicha situación es un error de programación
lógico, nunca finalizará el programa.

Problema 1:
Realizar un programa que imprima en pantalla los números del 1 al 100.
Sin conocer las estructuras repetitivas podemos resolver el problema
empleando una estructura secuencial. Iniciamos una variable con el valor 1,
luego imprimimos la variable, incrementamos nuevamente la variable y así
sucesivamente.
Diagrama de flujo:

Si continuamos con el diagrama veríamos que es casi interminable.


Emplear una estructura secuencial para resolver este problema produce un
diagrama de flujo y un programa en Python muy largo.
Ahora veamos la solución empleando una estructura repetitiva while:
Es muy importante analizar este diagrama:
La primera operación inicializa la variable x en 1, seguidamente comienza la
estructura repetitiva while y disponemos la siguiente condición ( x <= 100), se
lee MIENTRAS la variable x sea menor o igual a 100.
Al ejecutarse la condición retorna VERDADERO porque el contenido de x (1)
es menor o igual a 100. Al ser la condición verdadera se ejecuta el bloque de
instrucciones que contiene la estructura while. El bloque de instrucciones
contiene una salida y una operación.
Se imprime el contenido de x, y seguidamente se incrementa la variable x en
uno.
La operación x=x+1 se lee como "en la variable x se guarda el contenido de x
más 1". Es decir, si x contiene 1 luego de ejecutarse esta operación se
almacenará en x un 2.
Al finalizar el bloque de instrucciones que contiene la estructura repetitiva se
verifica nuevamente la condición de la estructura repetitiva y se repite el
proceso explicado anteriormente.
Mientras la condición retorne verdadero se ejecuta el bloque de instrucciones;
al retornar falso la verificación de la condición se sale de la estructura repetitiva
y continua el algoritmo, en este caso finaliza el programa.
Lo más difícil es la definición de la condición de la estructura while y que
bloque de instrucciones se van a repetir. Observar que si, por ejemplo,
disponemos la condición x >=100 ( si x es mayor o igual a 100) no provoca
ningún error sintáctico pero estamos en presencia de un error lógico porque al
evaluarse por primera vez la condición retorna falso y no se ejecuta el bloque
de instrucciones que queríamos repetir 100 veces.
No existe una RECETA para definir una condición de una estructura repetitiva,
sino que se logra con una práctica continua solucionando problemas.
Una vez planteado el diagrama debemos verificar si el mismo es una solución
válida al problema (en este caso se debe imprimir los números del 1 al 100 en
pantalla), para ello podemos hacer un seguimiento del flujo del diagrama y los
valores que toman las variables a lo largo de la ejecución:

x
1
2
3
4
.
.
100
101 Cuando x vale 101 la condición de la estructura repetitiva retorna
falso,
en este caso finaliza el diagrama.

Importante: Podemos observar que el bloque repetitivo puede no ejecutarse


ninguna vez si la condición retorna falso la primera vez.
La variable x debe estar inicializada con algún valor antes que se ejecute la
operación x=x+1 en caso de no estar inicializada aparece un error de
compilación.
Programa: ejercicio28.py
Ver video

x=1
while x<=100:
print(x)
x=x+1
Recordemos que un problema no estará 100% solucionado si no codificamos
el programa en nuestro caso en Python que muestre los resultados buscados.
Es importante notar que seguido de la palabra clave while disponemos la
condición y finalmente los dos puntos. Todo el código contenido en la
estructura repetitiva debe estar indentado (normalmente a cuatro espacios)
Probemos algunas modificaciones de este programa y veamos que cambios se
deberían hacer para:

1 - Imprimir los números del 1 al 500.


2 - Imprimir los números del 50 al 100.
3 - Imprimir los números del -50 al 0.
4 - Imprimir los números del 2 al 100 pero de 2 en 2 (2,4,6,8 ....100).

Respuestas:

1 - Debemos cambiar la condición del while con x<=500.


2 - Debemos inicializar x con el valor 50.
3 - Inicializar x con el valor -50 y fijar la condición x<=0.
4 - Inicializar a x con el valor 2 y dentro del bloque repetitivo incrementar a
x en 2
( x = x + 2 )

Problema 2:
Codificar un programa que solicite la carga de un valor positivo y nos muestre
desde 1 hasta el valor ingresado de uno en uno.
Ejemplo: Si ingresamos 30 se debe mostrar en pantalla los números del 1 al
30.
Es de FUNDAMENTAL importancia analizar los diagramas de flujo y la
posterior codificación en Python de los siguientes problemas, en varios
problemas se presentan otras situaciones no vistas en el ejercicio anterior.
Diagrama de flujo:

Podemos observar que se ingresa por teclado la variable n. El operador puede


cargar cualquier valor.
Si el usuario carga 10 el bloque repetitivo se ejecutará 10 veces, ya que la
condición es “Mientras x<=n ”, es decir “mientras x sea menor o igual a 10”;
pues x comienza en uno y se incrementa en uno cada vez que se ejecuta el
bloque repetitivo.
A la prueba del diagrama la podemos realizar dándole valores a las variables;
por ejemplo, si ingresamos 5 el seguimiento es el siguiente:

n x
5 1 (Se imprime el contenido de x)
2 " "
3 " "
4 " "
5 " "
6 (Sale del while porque 6 no es menor o igual a 5)

Programa: ejercicio29.py
Ver video

n=int(input("Ingrese el valor final:"))


x=1
while x<=n:
print(x)
x=x+1
Los nombres de las variables n y x pueden ser palabras o letras (como en este
caso)
La variable x recibe el nombre de CONTADOR. Un contador es un tipo especial
de variable que se incrementa o disminuye con valores constantes durante la
ejecución del programa.
El contador x nos indica en cada momento la cantidad de valores impresos en
pantalla.

Problema 3:
Desarrollar un programa que permita la carga de 10 valores por teclado y nos
muestre posteriormente la suma de los valores ingresados y su promedio.
Diagrama de flujo:

En este problema, a semejanza de los anteriores, tenemos un CONTADOR


llamado x que nos sirve para contar las vueltas que debe repetir el while.
También aparece el concepto de ACUMULADOR (un acumulador es un tipo
especial de variable que se incrementa o disminuye con valores variables
durante la ejecución del programa)
Hemos dado el nombre de suma a nuestro acumulador. Cada ciclo que se
repita la estructura repetitiva, la variable suma se incrementa con el contenido
ingresado en la variable valor.
La prueba del diagrama se realiza dándole valores a las variables:

valor suma x promedio


0 0
(Antes de entrar a la estructura repetitiva estos son los valores).
5 5 1
16 21 2
7 28 3
10 38 4
2 40 5
20 60 6
5 65 7
5 70 8
10 80 9
2 82 10
8 90 11
9

Este es un seguimiento del diagrama planteado. Los números que toma la


variable valor dependerá de qué cifras cargue el operador durante la ejecución
del programa.
El promedio se calcula al salir de la estructura repetitiva (es decir primero
sumamos los 10 valores ingresados y luego los dividimos por 10)
Hay que tener en cuenta que cuando en la variable valor se carga el primer
valor (en este ejemplo 5) al cargarse el segundo valor (16) el valor anterior 5 se
pierde, por ello la necesidad de ir almacenando en la variable suma los valores
ingresados.
Programa: ejercicio30.py
Ver video
x=1
suma=0
while x<=10:
valor=int(input("Ingrese un valor:"))
suma=suma+valor
x=x+1
promedio=suma/10
print("La suma de los 10 valores es")
print(suma)
print("El promedio es")
print(promedio)
El resultado del promedio es un valor real es decir con coma. Si queremos que
el resultado de la división solo retorne la parte entera del promedio debemos
utilizar el operador //:

promedio=suma//10

El interprete de Python sabe que el promedio se calcula al finalizar el while ya


que se encuentra codificado en la columna 1. Las tres instrucciones contenidas
en el while están indentadas.

Problema 4:
Una planta que fabrica perfiles de hierro posee un lote de n piezas.
Confeccionar un programa que pida ingresar por teclado la cantidad de piezas
a procesar y luego ingrese la longitud de cada perfil; sabiendo que la pieza
cuya longitud esté comprendida en el rango de 1.20 y 1.30 son aptas. Imprimir
por pantalla la cantidad de piezas aptas que hay en el lote.
Diagrama de flujo:

Podemos observar que dentro de una estructura repetitiva puede haber


estructuras condicionales (inclusive puede haber otras estructuras repetitivas
que veremos más adelante)
En este problema hay que cargar inicialmente la cantidad de piezas a ingresar
( n ), seguidamente se cargan n valores de largos de piezas.
Cada vez que ingresamos un largo de pieza (largo) verificamos si es una
medida correcta (debe estar entre 1.20 y 1.30 el largo para que sea correcta),
en caso de ser correcta la CONTAMOS (incrementamos la variable cantidad en
1)
Al contador cantidad lo inicializamos en cero porque inicialmente no se ha
cargado ningún largo de pieza.
Cuando salimos de la estructura repetitiva porque se han cargado n largos de
piezas mostramos por pantalla el contador cantidad (que representa la
cantidad de piezas aptas)
En este problema tenemos dos CONTADORES:

x (Cuenta la cantidad de piezas cargadas hasta el momento)


cantidad (Cuenta los perfiles de hierro aptos)

Programa: ejercicio31.py
Ver video

cantidad=0
x=1
n=int(input("Cuantas piezas cargara:"))
while x<=n:
largo=float(input("Ingrese la medida de la pi
eza:"))
if largo>=1.2 and largo<=1.3:
cantidad=cantidad+1
x=x+1
print("La cantidad de piezas aptas son")
print(cantidad)
Veamos algunas cosas nuevas:
Cuando queremos cargar por teclado un valor con decimales debemos utilizar
la función float en lugar de int:

largo=float(input("Ingrese la medida de la pieza:"))


Problemas propuestos
Ha llegado la parte fundamental, que es el momento donde uno desarrolla
individualmente un algoritmo para la resolución de problemas.
El tiempo a dedicar a esta sección EJERCICIOS PROPUESTOS debe ser
mucho mayor que el empleado a la sección de EJERCICIOS RESUELTOS.
La experiencia dice que debemos dedicar el 80% del tiempo a la resolución
individual de problemas y el otro 20% al análisis y codificación de problemas ya
resueltos por otras personas.
Es de vital importancia para llegar a ser un buen PROGRAMADOR poder
resolver problemas en forma individual.

• Escribir un programa que solicite ingresar 10 notas de alumnos y nos


informe cuántos tienen notas mayores o iguales a 7 y cuántos menores.

Ver video

• Se ingresan un conjunto de n alturas de personas por teclado. Mostrar la


altura promedio de las personas.

Ver video

• En una empresa trabajan n empleados cuyos sueldos oscilan entre $100


y $500, realizar un programa que lea los sueldos que cobra cada
empleado e informe cuántos empleados cobran entre $100 y $300 y
cuántos cobran más de $300. Además el programa deberá informar el
importe que gasta la empresa en sueldos al personal.

Ver video

• Realizar un programa que imprima 25 términos de la serie 11 - 22 - 33 -


44, etc. (No se ingresan valores por teclado)

Ver video

• Mostrar los múltiplos de 8 hasta el valor 500. Debe aparecer en pantalla


8 - 16 - 24, etc.

Ver video

• Realizar un programa que permita cargar dos listas de 15 valores cada


una. Informar con un mensaje cual de las dos listas tiene un valor
acumulado mayor (mensajes "Lista 1 mayor", "Lista 2 mayor", "Listas
iguales")
Tener en cuenta que puede haber dos o más estructuras repetitivas en
un algoritmo.

Ver video

• Desarrollar un programa que permita cargar n números enteros y luego


nos informe cuántos valores fueron pares y cuántos impares.
Emplear el operador “%” en la condición de la estructura condicional
(este operador retorna el resto de la división de dos valores, por ejemplo
11%2 retorna un 1):

• if valor%2==0:

Ver video
Solución

Retornar
10 - Estructura repetitiva for
Cualquier problema que requiera una estructura repetitiva se puede resolver
empleando la estructura while, pero hay otra estructura repetitiva cuyo planteo
es más sencillo en ciertas situaciones que tenemos que recorrer una lista de
datos.
En general, la estructura repetitiva for se usa en aquellas situaciones en las
cuales queremos que una variable vaya tomando un valor de una lista definida
de valores.
Veremos con una serie de ejemplos el empleo del for.

Problema 1:
Realizar un programa que imprima en pantalla los números del 0 al 100. Este
problema lo podemos resolver perfectamente con el ciclo while pero en esta
situación lo resolveremos empleando el for.
Programa: ejercicio39.py
Ver video

for x in range(101):
print(x)
Tenemos primero la palabra clave for y seguidamente el nombre de la variable
que almacenará en cada vuelta del for el valor entero que retorna la función
range.
La función range retorna la primera vez el valor 0 y se almacena en x, luego el
1 y así sucesivamente hasta que retorna el valor que le pasamos a range
menos uno (es decir en nuestro ejemplo al final retorna un 100)
Tengamos en cuenta que este mismo problema resuelto con la estructura while
debería ser:
Programa: ejercicio40.py

x=0
while x<101:
print(x)
x=x+1

Problema 2:
Realizar un programa que imprima en pantalla los números del 20 al 30.
Programa: ejercicio41.py

for x in range(20,31):
print(x)
La función range puede tener dos parámetros, el primero indica el valor inicial
que tomará la variable x, cada vuelta del for la variable x toma el valor siguiente
hasta llegar al valor indicado por el segundo parámetro de la función range
menos uno.

Problema 3:
Imprimir todos los números impares que hay entre 1 y 100.
Programa: ejercicio42.py

for x in range(1,100,2):
print(x)
La función range puede tener también tres parámetros, el primero indica el
valor inicial que tomará la variable x, el segundo parámetro el valor final (que
no se incluye) y el tercer parámetro indica cuanto se incrementa cada vuelta x.
En nuestro ejemplo la primer vuelta del for x recibe el valor 1, la segunda vuelta
toma el valor 3 y así sucesivamente hasta el valor 99.

Problema 4:
Desarrollar un programa que permita la carga de 10 valores por teclado y nos
muestre posteriormente la suma de los valores ingresados y su promedio. Este
problema ya lo desarrollamos, lo resolveremos empleando la estructura for
para repetir la carga de los diez valores por teclado.
Programa: ejercicio43.py
Ver video

suma=0
for f in range(10):
valor=int(input("Ingrese valor:"))
suma=suma+valor
print("La suma es")
print(suma)
promedio=suma/10
print("El promedio es:")
print(promedio)
Como vemos la variable f del for solo sirve para iterar(repetir) las diez veces el
bloque contenido en el for.
El resultado hubiese sido el mismo si llamamos a la funcion range con los
valores: range(1,11)

Problema 5:
Escribir un programa que solicite por teclado 10 notas de alumnos y nos
informe cuántos tienen notas mayores o iguales a 7 y cuántos menores.
Programa: ejercicio44.py
Ver video
aprobados=0
reprobados=0
for f in range(10):
nota=int(input("Ingrese la nota:"))
if nota>=7:
aprobados=aprobados+1
else:
reprobados=reprobados+1
print("Cantidad de aprobados")
print(aprobados)
print("Cantidad de reprobados")
print(reprobados)
Nuevamente utilizamos el for ya que sabemos que el ciclo repetitivo debe
repetirse 10 veces. Recordemos que si utilizamos el while debemos llevar un
contador y recordar de incrementarlo en cada vuelta.

Problema 6:
Escribir un programa que lea 10 números enteros y luego muestre cuántos
valores ingresados fueron múltiplos de 3 y cuántos de 5. Debemos tener en
cuenta que hay números que son múltiplos de 3 y de 5 a la vez.
Programa: ejercicio45.py
Ver video

mul3=0
mul5=0
for f in range(10):
valor=int(input("Ingrese un valor:"))
if valor%3==0:
mul3=mul3+1
if valor%5==0:
mul5=mul5+1
print("Cantidad de valores ingresados múltiplos d
e 3")
print(mul3)
print("Cantidad de valores ingresados múltiplos d
e 5")
print(mul5)
Si ejecutamos el programa tenemos una salida similar a esta:

Problema 7:
Codificar un programa que lea n números enteros y calcule la cantidad de
valores mayores o iguales a 1000 (n se carga por teclado)
Este tipo de problemas también se puede resolver empleando la estructura
repetitiva for. Lo primero que se hace es cargar una variable que indique la
cantidad de valores a ingresar. Dicha variable se carga antes de entrar a la
estructura repetitiva for.
Programa: ejercicio46.py
Ver video

cantidad=0
n=int(input("Cuantos valores ingresará:"))
for f in range(n):
valor=int(input("Ingrese el valor:"))
if valor>=1000:
cantidad=cantidad+1
print("La cantidad de valores ingresados mayores
o iguales a 1000 son")
print(cantidad)

Problemas propuestos
Ha llegado nuevamente la parte fundamental, que es el momento donde uno
desarrolla individualmente un algoritmo para la resolución de un problema.

• Confeccionar un programa que lea n pares de datos, cada par de datos


corresponde a la medida de la base y la altura de un triángulo. El
programa deberá informar:
a) De cada triángulo la medida de su base, su altura y su superficie.
b) La cantidad de triángulos cuya superficie es mayor a 12.

Ver video

• Desarrollar un programa que solicite la carga de 10 números e imprima


la suma de los últimos 5 valores ingresados.

Ver video
• Desarrollar un programa que muestre la tabla de multiplicar del 5 (del 5
al 50)

Ver video

• Confeccionar un programa que permita ingresar un valor del 1 al 10 y


nos muestre la tabla de multiplicar del mismo (los primeros 12 términos)
Ejemplo: Si ingreso 3 deberá aparecer en pantalla los valores 3, 6, 9,
hasta el 36.

Ver video

• Realizar un programa que lea los lados de n triángulos, e informar:


a) De cada uno de ellos, qué tipo de triángulo es: equilátero (tres lados
iguales), isósceles (dos lados iguales), o escaleno (ningún lado igual)
b) Cantidad de triángulos de cada tipo.

Ver video

• Escribir un programa que pida ingresar coordenadas (x,y) que


representan puntos en el plano.
Informar cuántos puntos se han ingresado en el primer, segundo, tercer
y cuarto cuadrante. Al comenzar el programa se pide que se ingrese la
cantidad de puntos a procesar.

Ver video

• Se realiza la carga de 10 valores enteros por teclado. Se desea conocer:


a) La cantidad de valores ingresados negativos.
b) La cantidad de valores ingresados positivos.
c) La cantidad de múltiplos de 15.
d) El valor acumulado de los números ingresados que son pares.

Ver video

• Se cuenta con la siguiente información:


Las edades de 5 estudiantes del turno mañana.
Las edades de 6 estudiantes del turno tarde.
Las edades de 11 estudiantes del turno noche.
Las edades de cada estudiante deben ingresarse por teclado.
a) Obtener el promedio de las edades de cada turno (tres promedios)
b) Imprimir dichos promedios (promedio de cada turno)
c) Mostrar por pantalla un mensaje que indique cual de los tres turnos
tiene un promedio de edades mayor.
Ver video
Solución

Retornar

11 - Definición de comentarios en el
código fuente
Un programa en Python puede definir además del algoritmo propiamente dicho
una serie de comentarios en el código fuente que sirvan para aclarar los
objetivos de ciertas partes del programa.
Tengamos en cuenta que un programa puede requerir mantenimiento del
mismo en el futuro. Cuando hay que implementar cambios es bueno encontrar
en el programa comentarios sobre el objetivo de las distintas partes del
algoritmo, sobretodo si es complejo.
Existen dos formas de definir comentarios en Python:

• Comentarios de una sola línea, se emplea el caracter #:

• #definimos tres contadores

• conta1=0
• conta2=0

• conta3=0

Todo lo que disponemos después del caracter # no se ejecuta


• Comentarios de varias líneas:

• """Definimos tres contadores

• que se muestran si son distintos a cero"""

• conta1=0

• conta2=0
• conta3=0
Se deben utilizar tres comillas simples o dobles seguidas al principio y al
final del comentario.

Problema 1:
Mostrar la tabla de multiplicar del 5 empleando primero el while y seguidamente
de nuevo empleando el for.
Programa: ejercicio55.py
Ver video

"""
Mostrar la tabla de 5 con las estructuras repetit
ivas:
while
y
for
"""

#utilizando el while
print("Tabla del 5 empleando el while")
x=5
while x<=50:
print(x)
x=x+5

#utilizando el for
print("Tabla del 5 empleando el for")
for x in range(5,51,5):
print(x)
Problemas propuestos
• Realizar un programa que solicite la carga de valores enteros por teclado
y los sume. Finalizar la carga al ingresar el valor -1. Dejar como
comentario dentro del código fuente el enunciado del problema.

Ver video

• Confeccionar un programa que solicite la carga de 10 valores reales por


teclado. Mostrar al final su suma. Definir varias líneas de comentarios
indicando el nombre del programa, el programador y la fecha de la última
modificación. Utilizar el caracter # para los comentarios.

Ver video
Solución

Retornar

12 - Variables enteras, flotantes y


cadenas de caracteres
Hasta este momento hemos visto como definir variables enteras y flotantes.
Realizar su carga por asignación y por teclado.
Para iniciarlas por asignación utilizamos el operador =

#definición de una variable entera


cantidad=20
#definición de una variable flotante
altura=1.92

Como vemos el intérprete de Python diferencia una variable flotante de una


variable entera por la presencia del caracter punto.
Para realizar la carga por teclado utilizando la función input debemos llamar a
la función int o float para convertir el dato devuelto por input:

cantidad=int(input("Ingresar la cantidad de personas:"))


altura=float(input("Ingresar la altura de la persona en metros ej:1.70:"))

A estos dos tipos de datos fundamentales (int y float) se suma un tipo de dato
muy utilizado que son las cadenas de caracteres.
Una cadena de caracteres está compuesta por uno o más caracteres. También
podemos iniciar una cadena de caracteres por asignación o ingresarla por
teclado.
Inicialización de una cadena por asignación:

#definición e inicio de una cadena de caracteres


dia="lunes"

Igual resultado obtenemos si utilizamos la comilla simple:

#definición e inicio de una cadena de caracteres


dia='lunes'

Para la carga por teclado de una cadena de caracteres utilizamos la función


input que retorna una cadena de caracteres:

nombre=input("ingrese su nombre:")

Problema 1:
Realizar la carga por teclado del nombre, edad y altura de dos personas.
Mostrar por pantalla el nombre de la persona con mayor altura.
Programa: ejercicio58.py
Ver video

print("Datos de la primer persona")


nombre1=input("Ingrese nombre:")
edad1=int(input("Ingrese la edad:"))
altura1=float(input("Ingrese la altura Ej 1.75:")
)
print("Datos de la segunda persona")
nombre2=input("Ingrese nombre:")
edad2=int(input("Ingrese la edad:"))
altura2=float(input("Ingrese la altura Ej 1.75:")
)
print("La persona mas alta es:")
if altura1>altura2:
print(nombre1)
else:
print(nombre2)
Es importante notar que cuando cargamos un entero el dato devuelto por la
función input se lo pasamos a la función int que tiene por objetivo convertirlo a
entero:

edad1=int(input("Ingrese la edad:"))

Cuando cargamos un valor con decimal el dato devuelto por la función input se
lo pasamos a la función float que tiene por objetivo convertirlo a float:

altura1=float(input("Ingrese la altura Ej 1.75:"))

Finalmente cuando cargamos una cadena de caracteres como es en este caso


el nombre de una persona la función input retorna directamente una cadena de
caracteres.

nombre1=input("Ingrese nombre:")

Problema 2:
Realizar la carga de dos nombres por teclado. Mostrar cual de los dos es
mayor alfabéticamente o si son iguales.
Programa: ejercicio59.py
Ver video

nombre1=input("Ingrese el primer nombre:")


nombre2=input("Ingrese el segundo nombre:")
if nombre1==nombre2:
print("Ingreso dos nombre iguales")
else:
if nombre1>nombre2:
print(nombre1)
print("es mayor alfabeticamente")
else:
print(nombre2)
print("es mayor alfabeticamente")
Cuando trabajamos con cadenas de caracteres al utilizar el operador >
estamos verificando si una cadena es mayor alfabéticamente a otra (esto es
distinto a cuando trabajamos con enteros o flotantes)
Por ejemplo 'luis' es mayor a 'carlos' porque la 'l' se encuentra más adelante en
el abecedario que la 'c'.

Problema 3:
Realizar la carga de enteros por teclado. Preguntar después que ingresa el
valor si desea cargar otro valor debiendo el operador ingresar la cadena 'si' o
'no' por teclado.
Mostrar la suma de los valores ingresados.
Programa: ejercicio60.py
Ver video

opcion="si"
suma=0
while opcion=="si":
valor=int(input("Ingrese un valor:"))
suma=suma+valor
opcion=input("Desea cargar otro numero (si/no
):")
print("La suma de valores ingresados es")
print(suma)
Para resolver este problema hemos inicializado una variable de tipo cadena de
caracteres (también se las llama variables de tipo string) con el valor "si", esto
hace que la condición del while se verifique verdadera la primera vez. Dentro
del while luego de cargar el valor entero se pide la carga por teclado que
confirme si desea cargar otro valor, en caso que cargue el string "si" el ciclo
repetitivo while se vuelve a repetir.
El ciclo se corta cuando el operador carga un string distinto a "si".
Es importante notar que el string "si" es distinto al string "Si", es decir las
mayúsculas no tienen el mismo valor alfabético que las minúsculas (después
veremos que podemos convertir mayúsculas a minúsculas y viceversa)

Problema propuesto
• Realizar la carga de dos nombres de personas distintos. Mostrar por
pantalla luego ordenados en forma alfabética.
Ver video
Solución

Retornar

13 - Procesar cadenas de caracteres


Ya hemos visto que podemos cargar una cadena de caracteres por asignación:

#con doble comillas


cadena1="juan"
#el resultado es igual con simple comillas
cadena2='ana'

También podemos cargarla por teclado:

nombre=input("Ingrese su nombre:")

Podemos utilizar los operadores relacionales para identificar si dos cadenas


son iguales, distintas o cual es la mayor alfabética:

== Igualdad

!= Desigualdad
< menor

<= menor o igual

> mayor

>= mayor o igual

Como su nombre lo indica una cadena de caracteres está formada


generalmente por varios caracteres (de todos modos podría tener solo un
caracter o ser una cadena vacía)
Podemos acceder en forma individual a cada caracter del string mediante un
subíndice:

nombre='juan'
print(nombre[0]) #se imprime una j
if nombre[0]=="j": #verificamos si el primer caracter del string es una j
print(nombre)
print("comienza con la letra j")

Los subíndices comienzan a numerarse a partir del cero.


Si queremos conocer la longitud de un string en Python disponemos de una
función llamada len que retorna la cantidad de caracteres que contiene:

nombre='juan'
print(len(nombre))

El programa anterior imprime un 4 ya que la cadena nombre almacena 'juan'


que tiene cuatro caracteres.

Problema 1:
Realizar la carga del nombre de una persona y luego mostrar el primer caracter
del nombre y la cantidad de letras que lo componen.
Programa: ejercicio62.py

nombre=input("Ingrese su nombre:")
print("Primer caracter")
print(nombre[0])
print("Cantidad de letras del nombre:")
print(len(nombre))

Problema 2:
Solicitar la carga del nombre de una persona en minúsculas. Mostrar un
mensaje si comienza con vocal dicho nombre.
Programa: ejercicio63.py
Ver video

nombre=input("Ingrese su nombre:")
if nombre[0]=="a" or nombre[0]=="e" or nombre[0]=
="i" or nombre[0]=="o" or nombre[0]=="u":
print("El nombre ingresado comienza con vocal
")
else:
print("El nombre ingresado no comienza con vo
cal")
Con que una de las condiciones del if sea verdadera luego se ejecuta el bloque
del verdadero.

Problema 3:
Ingresar un mail por teclado. Verificar si el string ingresado contiene solo un
caracter "@".
Programa: ejercicio64.py
Ver video

mail=input("Ingrese un mail:")
cantidad=0
x=0
while x<len(mail):
if mail[x]=="@":
cantidad=cantidad+1
x=x+1
if cantidad==1:
print("Contiene solo un caracter @ el mail in
gresado")
else:
print("Incorrecto")
Para analizar cada caracter del string ingresado disponemos una estructura
while utilizando un contador llamado x que comienza con el valor cero y se
repetirá tantas veces como caracteres tenga la cadena (mediante la función len
obtenemos la cantidad de caracteres):

while x<len(mail):

Dentro del ciclo while verificamos cada caracter mediante un if y contamos la


cantidad de caracterers "@":

if mail[x]=="@":
cantidad=cantidad+1

Cuando sale del ciclo while procedemos a verificar si el contador tiene


almacenado el valor 1 y mostramos el mensaje respectivo:

if cantidad==1:
print("Contiene solo un caracter @ el mail ingresado")
else:
print("Incorrecto")

Los string en Python son inmutables, esto quiere decir que una vez que los
inicializamos no podemos modificar su contenido:

nombre="juan"
nombre[0]="m" #esto no se puede
No hay que confundir cambiar parte del string con realizar la asignación de otro
string a la misma variable, luego si es correcto asignar otro valor a un string:

nombre="juan"
print(nombre)
nombre="ana"
print(nombre)
Métodos propios de las cadenas de caracteres.
Los string tienen una serie de métodos (funciones aplicables solo a los string)
que nos facilitan la creación de nuestros programas.
Los primeros tres métodos que veremos se llaman: lower, upper y capitalize.

• upper() : devuelve una cadena de caracteres convertida todos sus


caracteres a mayúsculas.

• lower() : devuelve una cadena de caracteres convertida todos sus


caracteres a minúsculas.

• capitalize() : devuelve una cadena de caracteres convertida a mayúscula


solo su primer caracter y todos los demás a minúsculas.

Problema 4:
Inicializar un string con la cadena "mAriA" luego llamar a sus métodos upper(),
lower() y capitalize(), guardar los datos retornados en otros string y mostrarlos
por pantalla.
Programa: ejercicio65.py
Ver video
nombre1="mAriA"
print(nombre1)
nombre2=nombre1.upper()
print(nombre2)
nombre3=nombre1.lower()
print(nombre3)
nombre4=nombre1.capitalize()
print(nombre4)
El resultado de ejecutar este programa es:

Para llamar a un método del string debemos disponer entre el nombre del
string y el método el caracter punto:

nombre2=nombre1.upper()
Es importante decir que el string nombre1 no se modifica su contenido
(recordar que un string es inmutable) pero el método upper() retorna el
contenido de la variable nombre1 pera convertida a mayúsculas. El dato
devuelto se almacena en la variable nombre2.

Problemas propuestos
• Cargar una oración por teclado. Mostrar luego cuantos espacios en
blanco se ingresaron. Tener en cuenta que un espacio en blanco es
igual a
" ", en cambio una cadena vacía es ""

Ver video

• Ingresar una oración que pueden tener letras tanto en mayúsculas como
minúsculas. Contar la cantidad de vocales. Crear un segundo string con
toda la oración en minúsculas para que sea más fácil disponer la
condición que verifica que es una vocal.

Ver video

• Solicitar el ingreso de una clave por teclado y almacenarla en una


cadena de caracteres. Controlar que el string ingresado tenga entre 10 y
20 caracteres para que sea válido, en caso contrario mostrar un mensaje
de error.

Ver video
Solución

Retornar

14 - Estructura de datos tipo lista


Hasta ahora hemos trabajado con variables que permiten almacenar un único
valor:

edad=12
altura=1.79
nombre="juan"

En Python existe un tipo de variable que permite almacenar una colección de


datos y luego acceder por medio de un subíndice (similar a los string)

Creación de la lista por asignación


Para crear una lista por asignación debemos indicar sus elementos encerrados
entre corchetes y separados por coma.

lista1=[10, 5, 3] # lista de enteros


lista2=[1.78, 2.66, 1.55, 89,4] # lista de valores float
lista3=["lunes", "martes", "miercoles"] # lista de string
lista4=["juan", 45, 1.92] # lista con elementos de distinto tipo

Si queremos conocer la cantidad de elementos de una lista podemos llamar a


la función len:

lista1=[10, 5, 3] # lista de enteros


print(len(lista1)) # imprime un 3

Problema 1:
Definir una lista que almacene 5 enteros. Sumar todos sus elementos y mostrar
dicha suma.
Programa: ejercicio69.py
Ver video

lista=[10,7,3,7,2]
suma=0
x=0
while x<len(lista):
suma=suma+lista[x]
x=x+1
print("Los elementos de la lista son")
print(lista)
print("La suma de todos sus elementos es")
print(suma)

Primero definimos una lista por asignación con 5 elementos:

lista=[10,7,3,7,2]

Definimos un acumulador para sumar los elementos de la lista y un contador


para indicar que posición de la lista accedemos:

suma=0
x=0

Mediante un ciclo while recorremos y sumamos cada elementos de la lista:

while x<len(lista):
suma=suma+lista[x]
x=x+1
Cuando llamamos a la función print pasando como dato una lista luego se
muestra en pantalla todos los elementos de la lista entre corchetes y
separados por coma tal cual como la definimos:

print("Los elementos de la lista son")


print(lista)

Finalmente mostramos el acumulador:

print("La suma de todos sus elementos es")


print(suma)

Problema 2:
Definir una lista por asignación que almacene los nombres de los primeros
cuatro meses de año. Mostrar el primer y último elemento de la lista solamente.
Programa: ejercicio70.py
Ver video

meses=["enero", "febrero", "marzo", "abril"]


print(meses[0]) # se muestra enero
print(meses[3]) # se muestra abril
Como queremos imprimir solo el primer y último elemento de la lista indicamos
entre corchetes la posición de la lista del cual queremos rescatar el valor.
Si llamamos a print y pasamos solo el nombre de la lista luego se nos muestra
todos los elementos:

print(meses) # se muestra ["enero", "febrero", "marzo", "abril"]

Problema 3:
Definir una lista por asignación que almacene en la primer componente el
nombre de un alumno y en las dos siguientes sus notas. Imprimir luego el
nombre y el promedio de las dos notas.
Programa: ejercicio71.py
Ver video

lista=["ana", 7, 9]
print("Nombre del alumno:")
print(lista[0])
promedio=(lista[1]+lista[2])//2
print("Promedio de sus dos notas:")
print(promedio)
Como vemos en este problema los elementos de una lista pueden ser de
distinto tipo, aquí tenemos el primer elemento de tipo string y los dos siguientes
de tipo int.
Recordemos que el operador // se utiliza para dividir dos valores y retornar solo
la parte entera.

Problemas propuestos
• Definir por asignación una lista con 8 elementos enteros. Contar cuantos
de dichos valores almacenan un valor superior a 100.

Ver video

• Definir una lista por asignación con 5 enteros. Mostrar por pantalla solo
los elementos con valor iguales o superiores a 7.

Ver video

• Definir una lista que almacene por asignación los nombres de 5


personas. Contar cuantos de esos nombres tienen 5 o más caracteres.

Ver video
Solución

Retornar

15 - Listas: carga por teclado de sus


elementos
Una lista en Python es una estructura mutable (es decir puede ir cambiando
durante la ejecución del programa)
Hemos visto que podemos definir una lista por asignación indicando entre
corchetes los valores a almacenar:

lista=[10, 20, 40]

Una lista luego de definida podemos agregarle nuevos elementos a la


colección. La primera forma que veremos para que nuestra lista crezca es
utilizar el método append que tiene la lista y pasar como parámetro el nuevo
elemento:

lista=[10, 20, 30]


print(len(lista)) # imprime un 3
lista.append(100)
print(len(lista)) # imprime un 4
print(lista[0]) # imprime un 10
print(lista[3]) # imprime un 100

Definimos una lista con tres elementos:

lista=[10, 20, 30]

Imprimimos la cantidad de elementos que tiene la lista, en nuestro caso lo


definimos con 3:

print(len(lista)) # imprime un 3

Agregamos una nuevo elemento al final de la lista llamando al método append:

lista.append(100)

Si llamamos nuevamente a la función len y le pasamos el nombre de nuestra


lista ahora retorna un 4:

print(len(lista)) # imprime un 4

Imprimimos ahora el primer y cuarto elemento de la lista (recordar que se


numeran a partir de cero):

print(lista[0]) # imprime un 10
print(lista[3]) # imprime un 100
Problema 1:
Definir una lista vacía y luego solicitar la carga de 5 enteros por teclado y
añadirlos a la lista. Imprimir la lista generada.
Programa: ejercicio75.py
Ver video

#definimos una lista vacia


lista=[]
#disponemos un ciclo de 5 vueltas
for x in range(5):
valor=int(input("Ingrese un valor entero:"))
lista.append(valor)

#imprimimos la lista
print(lista)
El algoritmo propuesto crea primero una lista vacía (debemos asignar los
corchetes de apertura y cerrado sin contenido):

lista=[]

Luego mediante un for (podemos utilizar un while si queremos) solicitamos en


forma sucesiva la carga de un entero por teclado y procedemos a agregarlo al
final de la lista llamando al método append:

for x in range(5):
valor=int(input("Ingrese un valor entero:"))
lista.append(valor)

Finalmente mostramos los elementos de la lista creada:

print(lista)

Problema 2:
Realizar la carga de valores enteros por teclado, almacenarlos en una lista.
Finalizar la carga de enteros al ingresar el cero. Mostrar finalmente el tamaño
de la lista.
Programa: ejercicio76.py
Ver video

lista=[]
valor=int(input("Ingresar valor (0 para finalizar
):"))
while valor!=0:
lista.append(valor)
valor=int(input("Ingresar valor (0 para final
izar):"))

print("Tamano de la lista:")
print(len(lista))
En este problema la lista crecerá hasta que el operador ingrese el valor cero.
La carga del primer valor se efectúa antes del ciclo while ya que la condición
depende del valor ingresado:

valor=int(input("Ingresar valor (0 para finalizar):"))

Luego dentro del ciclo while procedemos a agregar al final de la lista el valor
ingresado y solicitar la carga del siguiente valor:

while valor!=0:
lista.append(valor)
valor=int(input("Ingresar valor (0 para finalizar):"))

Cuando salimos del ciclo repetitivo procedemos a obtener el tamaño de la lista


mediante la función len:

print(len(lista))

Problemas propuestos
• Almacenar en una lista los sueldos (valores float) de 5 operarios.
Imprimir la lista y el promedio de sueldos.

Ver video

• Cargar por teclado y almacenar en una lista las alturas de 5 personas


(valores float)
Obtener el promedio de las mismas. Contar cuántas personas son más
altas que el promedio y cuántas más bajas.

Ver video

• Una empresa tiene dos turnos (mañana y tarde) en los que trabajan 8
empleados (4 por la mañana y 4 por la tarde) Confeccionar un programa
que permita almacenar los sueldos de los empleados agrupados en dos
listas.
Imprimir las dos listas de sueldos.

Ver video
Solución

Retornar

16 - Listas: mayor y menor elemento


Es una actividad muy común la búsqueda del mayor y menor elemento de una
lista.
Es necesario que la lista tenga valores del mismo tipo por ejemplo enteros.
Pueden ser de tipo cadenas de caracteres y se busque cual es mayor o menor
alfabéticamente, pero no podemos buscar el mayor o menor si la lista tiene
enteros y cadenas de caracteres al mismo tiempo.

Problema 1:
Crear y cargar una lista con 5 enteros. Implementar un algoritmo que
identifique el mayor valor de la lista.
Ver video
Programa: ejercicio80.py

lista=[]
for x in range(5):
valor=int(input("Ingrese valor:"))
lista.append(valor)

mayor=lista[0]
for x in range(1,5):
if lista[x]>mayor:
mayor=lista[x]

print("Lista completa")
print(lista)
print("Mayor de la lista")
print(mayor)
Primero procedemos a cargar por teclado los 5 valores en la lista:

for x in range(5):
valor=int(input("Ingrese valor:"))
lista.append(valor)

Para identificar el mayor de una lista primero tomamos como referencia el


primer elemento, considerando a este en principio como el mayor de la lista:

mayor=lista[0]

Seguidamente disponemos un for que se repita 4 veces esto debido a que no


debemos controlar el primer elemento de la lista (recordar que la primer vuelta
del for x toma el valor 1, luego el 2 y así sucesivamente hasta el 4):

for x in range(1,5):
Dentro del for mediante una estructura condicional verificamos si el elemento
de la posición x de la lista es mayor al que hemos considerado hasta este
momento como mayor:

if lista[x]>mayor:
mayor=lista[x]

Como vemos en las dos líneas anteriores si el if se verifica verdadero


actualizamos la variable mayor con el elemento de la lista que estamos
analizando.
Cuando finaliza el for procedemos a mostrar el contenido de la variable "mayor"
que tiene almacenado el mayor elemento de la lista:

print("Mayor de la lista")
print(mayor)

Problema 2:
Crear y cargar una lista con 5 enteros por teclado. Implementar un algoritmo
que identifique el menor valor de la lista y la posición donde se encuentra.
Programa: ejercicio81.py
Ver video

lista=[]
for x in range(5):
valor=int(input("Ingrese valor:"))
lista.append(valor)

menor=lista[0]
posicion=0
for x in range(1,5):
if lista[x]<menor:
menor=lista[x]
posicion=x
print("Lista completa")
print(lista)
print("Menor de la lista")
print(menor)
print("Posicion del menor en la lista")
print(posicion)
Iniciamos una lista vacía y cargamos 5 elementos enteros:

lista=[]
for x in range(5):
valor=int(input("Ingrese valor:"))
lista.append(valor)

Para identificar el menor y la posición de dicho valor en la lista definimos dos


variables. La primera le cargamos el primer elemento de la lista, que es el que
consideramos como menor hasta este momento:

menor=lista[0]

Por otro lado la segunda variable almacena un cero que es la posición donde
se encuentra el menor hasta este momento:

posicion=0

Seguidamente disponemos un for que se repita 4 veces (que son la cantidad


de elementos que nos faltan analizar de la lista):

for x in range(1,5):

Dentro del for mediante un if verificamos si el elemento que estamos


analizando de la lista es menor a la variable "menor":

if lista[x]<menor:

En caso que sea menor a la que hemos considerado "menor" hasta este
momento procedemos a actualizar la variable "menor" con el nuevo valor y
también actualizamos la variable "posicion" con el valor del contador del for que
nos indica que posición de la lista estamos analizando:
menor=lista[x]
posicion=x

Cuando salimos del for mostramos la lista completa, el menor de la lista y la


posición que tiene en la lista dicho menor:

print("Lista completa")
print(lista)
print("Menor de la lista")
print(menor)
print("Posicion del menor en la lista")
print(posicion)

Problemas propuestos
• Ingresar por teclado los nombres de 5 personas y almacenarlos en una
lista. Mostrar el nombre de persona menor en orden alfabético.

Ver video

• Cargar una lista con 5 elementos enteros. Imprimir el mayor y un


mensaje si se repite dentro de la lista (es decir si dicho valor se
encuentra en 2 o más posiciones en la lista)

Ver video
Solución

Retornar

17 - Listas paralelas
Podemos decir que dos listas son paralelas cuando hay una relación entre las
componentes de igual subíndice (misma posición) de una lista y otra.
Si tenemos dos listas que ya hemos inicializado con 5 elementos cada una. En
una se almacenan los nombres de personas en la otra las edades de dichas
personas.
Decimos que la lista nombres es paralela a la lista edades si en la componente
0 de cada lista se almacena información relacionada a una persona (Juan - 12
años)
Es decir hay una relación entre cada componente de las dos listas.
Esta relación la conoce únicamente el programador y se hace para facilitar el
desarrollo de algoritmos que procesen los datos almacenados en las
estructuras de datos.

Problema 1:
Desarrollar un programa que permita cargar 5 nombres de personas y sus
edades respectivas. Luego de realizar la carga por teclado de todos los datos
imprimir los nombres de las personas mayores de edad (mayores o iguales a
18 años)
Programa: ejercicio84.py
Ver video

nombres=[]
edades=[]
for x in range(5):
nom=input("Ingrese el nombre de la persona:")
nombres.append(nom)
ed=int(input("Ingrese la edad de dicha person
a:"))
edades.append(ed)

print("Nombre de las personas mayores de edad:")


for x in range(5):
if edades[x]>=18:
print(nombres[x])
Definimos dos listas para almacenar los nombres y las edades de las personas
respectivamente:

nombres=[]
edades=[]

Mediante un for cargamos en forma simultanea un elemento de cada lista, es


decir un nombre de persona y la edad de dicha persona:

for x in range(5):
nom=input("Ingrese el nombre de la persona:")
nombres.append(nom)
ed=int(input("Ingrese la edad de dicha persona:"))
edades.append(ed)

Para imprimir los nombres de la personas mayores de edad procedemos a


analizar dentro de un for y mediante un if cada una de las edades almacenadas
en la lista "edades", en el caso que su valor sea mayor o igual a 18 mostramos
el elemento de la lista nombres de la misma posición:

for x in range(5):
if edades[x]>=18:
print(nombres[x])

Problemas propuestos
• Crear y cargar dos listas con los nombres de 5 productos en una y sus
respectivos precios en otra. Definir dos listas paralelas. Mostrar cuantos
productos tienen un precio mayor al primer producto ingresado.

Ver video

• En un curso de 4 alumnos se registraron las notas de sus exámenes y


se deben procesar de acuerdo a lo siguiente:
a) Ingresar nombre y nota de cada alumno (almacenar los datos en dos
listas paralelas)
b) Realizar un listado que muestre los nombres, notas y condición del
alumno. En la condición, colocar "Muy Bueno" si la nota es mayor o igual
a 8, "Bueno" si la nota está entre 4 y 7, y colocar "Insuficiente" si la nota
es inferior a 4.
c) Imprimir cuantos alumnos tienen la leyenda “Muy Bueno”.

Ver video

• Realizar un programa que pida la carga de dos listas numéricas enteras


de 4 elementos cada una. Generar una tercer lista que surja de la suma
de los elementos de la misma posición de cada lista. Mostrar esta tercer
lista.

Ver video
Solución

Retornar

18 - Listas: ordenamiento de sus


elementos
Otro algoritmo muy común que debe conocer y entender un programador es el
ordenamiento de una lista de datos.
El ordenamiento de una lista se logra intercambiando las componentes de
manera que:
lista[0] <= lista[1] <= lista[2] etc.
El contenido de la componente lista[0] sea menor o igual al contenido de la
componente lista[1] y así sucesivamente.
Si se cumple lo dicho anteriormente decimos que la lista está ordenado de
menor a mayor. Igualmente podemos ordenar una lista de mayor a menor.
Tengamos en cuenta que la estructura de datos lista en Python es mutable,
eso significa que podemos modificar sus elementos por otros.
Se puede ordenar tanto listas con componentes de tipo int, float como cadena
de caracteres. En este último caso el ordenamiento es alfabético.

Problema 1:
Se debe crear y cargar una lista donde almacenar 5 sueldos. Desplazar el valor
mayor de la lista a la última posición.
La primera aproximación para llegar en el próximo problema al ordenamiento
completo de una lista tiene por objetivo analizar los intercambios de elementos
dentro de la lista y dejar el mayor en la última posición.
El algoritmo consiste en comparar si la primera componente es mayor a la
segunda, en caso que la condición sea verdadera, intercambiamos los
contenidos de las componentes.
Vamos a suponer que se ingresan los siguientes valores por teclado:

1200
750
820
550
490

En este ejemplo: ¿es 1200 mayor a 750? La respuesta es verdadera, por lo


tanto intercambiamos el contenido de la componente 0 con el de la
componente 1.
Luego comparamos el contenido de la componente 1 con el de la componente
2: ¿Es 1200 mayor a 820?
La respuesta es verdadera entonces intercambiamos.
Si hay 5 componentes hay que hacer 4 comparaciones, por eso el for se repite
4 veces.
Generalizando: si la lista tiene N componentes hay que hacer N-1
comparaciones.

Cuando x = 0 x = 1 x = 2 x = 3

750 750 750 750


1200 820 820 820
820 1200 550 550
550 550 1200 490
490 490 490 1200

Podemos ver cómo el valor más grande de la lista desciende a la última


componente. Empleamos una variable auxiliar (aux) para el proceso de
intercambio:
Programa: ejercicio88.py
Ver video

sueldos=[]
for x in range(5):
valor=int(input("Ingrese sueldo:"))
sueldos.append(valor)

print("Lista sin ordenar")


print(sueldos)

for x in range(4):
if sueldos[x]>sueldos[x+1]:
aux=sueldos[x]
sueldos[x]=sueldos[x+1]
sueldos[x+1]=aux

print("Lista con el último elemento ordenado")


print(sueldos)
Al salir del for el contenido de la lista es la siguiente:

750
820
550
490
1200

Analizando el algoritmo podemos comprobar que el elemento mayor de la lista


se ubica ahora en el último lugar.
Podemos volver a ejecutar el programa y veremos que siempre el elemento
mayor queda al final.
Pero con un único for no se ordena una lista. Solamente está ordenado el
último elemento de la lista.

Problema 2:
Se debe crear y cargar una lista donde almacenar 5 sueldos. Ordenar de
menor a mayor la lista.
Ahora bien como vimos en el problema anterior con los 4 elementos que nos
quedan podemos hacer el mismo proceso visto anteriormente, con lo cual
quedará ordenado otro elemento de la lista. Este proceso lo repetiremos hasta
que quede ordenado por completo la lista.
Como debemos repetir el mismo algoritmo podemos englobar todo el bloque
en otra estructura repetitiva.
Realicemos una prueba del siguiente algoritmo:

Cuando k = 0
x = 0 x = 1 x = 2 x = 3
750 750 750 750
1200 820 820 820
820 1200 550 550
550 550 1200 490
490 490 490 1200

Cuando k = 1
x = 0 x = 1 x = 2 x = 3
750 750 750 750
820 550 550 550
550 820 490 490
490 490 820 820
1200 1200 1200 1200

Cuando k = 2
x = 0 x = 1 x = 2 x = 3
550 550 550 550
750 490 490 490
490 750 750 750
820 820 820 820
1200 1200 1200 1200

Cuando k = 3
x = 0 x = 1 x = 2 x = 3
490 490 490 490
550 550 550 550
750 750 750 750
820 820 820 820
1200 1200 1200 1200

Programa: ejercicio89.py
Ver video

sueldos=[]
for x in range(5):
valor=int(input("Ingrese sueldo:"))
sueldos.append(valor)

print("Lista sin ordenar")


print(sueldos)

for k in range(4):
for x in range(4):
if sueldos[x]>sueldos[x+1]:
aux=sueldos[x]
sueldos[x]=sueldos[x+1]
sueldos[x+1]=aux
print("Lista ordenada")
print(sueldos)
¿Porque repetimos 4 veces el for externo?
Como sabemos cada vez que se repite en forma completa el for interno queda
ordenada una componente de la lista. A primera vista diríamos que deberíamos
repetir el for externo la cantidad de componentes de la lista, en este ejemplo la
lista sueldos tiene 5 componentes.
Si observamos, cuando quedan dos elementos por ordenar, al ordenar uno de
ellos queda el otro automáticamente ordenado (podemos imaginar que si
tenemos una lista con 2 elementos no se requiere el for externo, porque este
debería repetirse una única vez)
Una última consideración a este ALGORITMO de ordenamiento es que los
elementos que se van ordenando continuamos comparándolos.
Ejemplo: En la primera ejecución del for interno el valor 1200 queda ubicado en
la posición 4 de la lista. En la segunda ejecución comparamos si el 820 es
mayor a 1200, lo cual seguramente será falso.
Podemos concluir que la primera vez debemos hacer para este ejemplo 4
comparaciones, en la segunda ejecución del for interno debemos hacer 3
comparaciones y en general debemos ir reduciendo en uno la cantidad de
comparaciones.
Si bien el algoritmo planteado funciona, un algoritmo más eficiente, que se
deriva del anterior es el plantear un for interno con la siguiente estructura:

for k in range(4):
for x in range(4-k):
if sueldos[x]>sueldos[x+1]:
aux=sueldos[x]
sueldos[x]=sueldos[x+1]
sueldos[x+1]=aux

Es decir restarle el valor del contador del for externo.

Problemas propuestos
• Crear una lista y almacenar los nombres de 5 países. Ordenar
alfabéticamente la lista e imprimirla.

Ver video

• Solicitar por teclado la cantidad de empleados que tiene la empresa.


Crear y cargar una lista con todos los sueldos de dichos empleados.
Imprimir la lista de sueldos ordenamos de menor a mayor.

Ver video

• Cargar una lista con 5 elementos enteros. Ordenarla de menor a mayor y


mostrarla por pantalla, luego ordenar de mayor a menor e imprimir
nuevamente.

Ver video
Solución
Retornar

19 - Listas: ordenamiento con listas


paralelas
Cuando se tienen listas paralelas y se ordenan los elementos de una de ellas
hay que tener la precaución de intercambiar los elementos de las listas
paralelas.

Problema 1:
Confeccionar un programa que permita cargar los nombres de 5 alumnos y sus
notas respectivas. Luego ordenar las notas de mayor a menor. Imprimir las
notas y los nombres de los alumnos.
Debe quedar claro que cuando intercambiamos las notas para dejarlas
ordenadas de mayor a menor debemos intercambiar los nombres para que las
listas continúen paralelas (es decir que en los mismos subíndices de cada lista
continúe la información relacionada)
Programa: ejercicio93.py
Ver video

alumnos=[]
notas=[]
for x in range(5):
nom=input("Ingrese el nombre del alumno:")
alumnos.append(nom)
no=int(input("Ingrese la nota de dicho alumno
:"))
notas.append(no)
for k in range(4):
for x in range(4-k):
if notas[x]<notas[x+1]:
aux1=notas[x]
notas[x]=notas[x+1]
notas[x+1]=aux1
aux2=alumnos[x]
alumnos[x]=alumnos[x+1]
alumnos[x+1]=aux2

print("Lista de alumnos y sus notas ordenadas de


mayor a menor")
for x in range(5):
print(alumnos[x],notas[x])
Definimos y cargamos dos listas con cinco elementos cada una:

alumnos=[]
notas=[]
for x in range(5):
nom=input("Ingrese el nombre del alumno:")
alumnos.append(nom)
no=int(input("Ingrese la nota de dicho alumno:"))
notas.append(no)

Lo nuevo se presenta cuando ordenamos la lista de notas de mayor a menor.


La condición dentro de los dos ciclos repetitivos depende de la lista notas, pero
en el caso que se verifique verdadera intercambiamos tanto los elementos de
la lista notas como el de la lista alumnos con el fin que continúen paralelas:

for k in range(4):
for x in range(4-k):
if notas[x]<notas[x+1]:
aux1=notas[x]
notas[x]=notas[x+1]
notas[x+1]=aux1
aux2=alumnos[x]
alumnos[x]=alumnos[x+1]
alumnos[x+1]=aux2

Imprimimos las dos listas:

for x in range(5):
print(alumnos[x],notas[x])

Algo que no habíamos utilizado en Python hasta ahora es imprimir varios datos
en la misma línea, esto se logra pasando más de un parámetro a la función
print separándolos por una coma:

print(alumnos[x],notas[x])

El resultado de ejecutar este programa:


Problema propuesto
• Crear y cargar en un lista los nombres de 5 países y en otra lista paralela
la cantidad de habitantes del mismo. Ordenar alfabéticamente e imprimir
los resultados. Por último ordenar con respecto a la cantidad de
habitantes (de mayor a menor) e imprimir nuevamente.

Ver video
Solución

Retornar
20 - Listas: componentes de tipo lista
Hasta ahora hemos trabajado con listas cuyos componentes son de tipo:

enteros
flotantes
cadenas de caracteres

Ejemplo

notas=[8, 6, 8]
alturas=[1.73, 1.55, 1.92]
dias=["lunes", "martes", "miércoles"]

Pero lo que la hace tan flexible a esta estructura de datos es que podemos
almacenar componentes de tipo LISTA.

notas=[[4,5], [6,9], [7,3]]

En la línea anterior hemos definido una lista de tres elementos de tipo lista, el
primer elemento de la lista es otra lista de dos elementos de tipo entero. De
forma similar los otros dos elementos de la lista notas son listas de dos
elementos de tipo entero.

Problema 1:
Crear una lista por asignación. La lista tiene que tener cuatro elementos. Cada
elemento debe ser una lista de 3 enteros.
Imprimir sus elementos accediendo de diferentes modos.
Programa: ejercicio95.py
Ver video

lista=[[1,2,3], [4,5,6], [7,8,9], [10,11,12]]

# imprimimos la lista completa


print(lista)
print("---------")
# imprimimos la primer componente
print(lista[0])
print("---------")
# imprimimos la primer componente de la lista con
tenida
# en la primer componente de la lista principal
print(lista[0][0])
print("---------")
# imprimimos con un for la lista contenida en la
primer componente
for x in range(len(lista[0])):
print(lista[0][x])
print("---------")
# imprimimos cada elemento entero de cada lista c
ontenida en la lista
for k in range(len(lista)):
for x in range(len(lista[k])):
print(lista[k][x])
El resultado de ejecutar este programa es:
Al principio puede complicarse trabajar con listas de listas pero a medida que
practiquemos esta estructura de datos veremos que podemos desarrollar
algoritmos más complejos.
Para definir y crear por asignación una lista de listas tenemos:

lista=[[1,2,3], [4,5,6], [7,8,9], [10,11,12]]

Queda claro que el primer elemento de lista es:

[1,2,3]

El segundo elemento de la variable lista es (y así sucesivamente):

[4,5,6]

La función print si le pasamos como parámetro el nombre de la lista nos


muestra la lista completa por pantalla:

print(lista)

Aparece:

[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]

Cuando pasamos a la función print el primer elemento de la lista:

print(lista[0])

Nos muestra la lista contenida en la primer componente de la lista principal:

[1, 2, 3]

Si queremos acceder al primer entero almacenado en la lista contenida en la


primer componente de la lista principal:

print(lista[0][0])

Nos muestra:

Para acceder mediante un for a todos los elementos de la lista contenida en la


primer componente de la lista principal debemos codificar:

for x in range(len(lista[0])):
print(lista[0][x])

Recordemos que la función len retorna la cantidad de elementos que contiene


una lista. En este caso le pasamos como parámetro lista[0] que hace referencia
a la primer componente de la lista principal.
El resultado de len(lista[0]) es un 3 que es la cantidad de elementos que tiene
la lista contenida en la primer componente de la lista principal.
Cada ciclo del for accedemos a: lista[0][0] cuando x vale 0, lista[0][1] cuando x
vale 1 y lista[0][2] cuando x vale 2.
Mediante este ciclo podemos acceder a cada elemento y procesarlo.
Por último con el ciclo anidado k podemos acceder a cada elemento de la lista
principal y mediante el for interno acceder a cada elemento entero de las listas
contenidas en la lista principal:

for k in range(len(lista)):
for x in range(len(lista[k])):
print(lista[k][x])

Problema 2:
Crear una lista por asignación. La lista tiene que tener 2 elementos. Cada
elemento debe ser una lista de 5 enteros.
Calcular y mostrar la suma de cada lista contenida en la lista principal.
Programa: ejercicio96.py
Ver video

lista=[[1,1,1,1,1], [2,2,2,2,2]]

suma1=lista[0][0]+lista[0][1]+lista[0][2]+lista[0
][3]+lista[0][4]
print(suma1)
suma2=lista[1][0]+lista[1][1]+lista[1][2]+lista[1
][3]+lista[1][4]
print(suma2)
print("----------")
suma1=0
for x in range(len(lista[0])):
suma1=suma1+lista[0][x]
suma2=0
for x in range(len(lista[1])):
suma2=suma2+lista[1][x]
print(suma1)
print(suma2)
print("----------")

for k in range(len(lista)):
suma=0
for x in range(len(lista[k])):
suma=suma+lista[k][x]
print(suma)
Hemos resuelto el problema de tres formas.
La primer forma es acceder a cada elemento en forma secuencial, esto se
resuelve de esta forma si tenemos que acceder a un pequeño número de
elementos, es decir si la lista es pequeña:

suma1=lista[0][0]+lista[0][1]+lista[0][2]+lista[0][3]+lista[0][4]
print(suma1)
suma2=lista[1][0]+lista[1][1]+lista[1][2]+lista[1][3]+lista[1][4]
print(suma2)

La segunda forma es utilizar una estructura repetitiva para sumar todos los
elementos de una lista (el primer subíndice siempre es 0 y el segundo varía
con la variable x):

suma1=0
for x in range(len(lista[0])):
suma1=suma1+lista[0][x]
suma2=0
for x in range(len(lista[1])):
suma2=suma2+lista[1][x]
print(suma1)
print(suma2)

La última forma planteada es utilizar una estructura repetitiva anidada que


suma cada fila, el for externo (k) se repite 2 veces que es el tamaño de la
variable "lista":

for k in range(len(lista)):
suma=0
for x in range(len(lista[k])):
suma=suma+lista[k][x]
print(suma)

Es importante notar que el acumulador suma lo iniciamos en 0 cada vez que


comenzamos a sumar una nueva lista.

Problema 3:
Crear una lista por asignación. La lista tiene que tener 5 elementos. Cada
elemento debe ser una lista, la primera lista tiene que tener un elemento, la
segunda dos elementos, la tercera tres elementos y así sucesivamente.
Sumar todos los valores de las listas.
Programa: ejercicio97.py
Ver video

lista=[[1], [1,2], [1,2,3], [1,2,3,4], [1,2,3,4,5


]]

suma=0
for k in range(len(lista)):
for x in range(len(lista[k])):
suma=suma+lista[k][x]
print(suma)
Lo primero que es importante notar que las listas contenidas en las lista
principal no tienen porque ser del mismo tamaño.
La forma más sencilla es utilizar dos ciclos repetitivos. El primero se repite
tantas veces como elementos tenga la lista principal:

for k in range(len(lista)):

El segundo ciclo nos sirve para recorrer y acceder a cada elemento entero de
cada lista:

for x in range(len(lista[k])):
suma=suma+lista[k][x]

La cantidad de veces que se repite el for interno depende de la cantidad de


elementos que tiene la lista que estamos sumando en ese momento.

Problemas propuestos
• Se tiene la siguiente lista:

• lista=[[100,7,85,8], [4,8,56,25], [67,89,23,1], [78,56]]

Imprimir la lista. Luego fijar con el valor cero todos los elementos
mayores a 50 del primer elemento de "lista".
Volver a imprimir la lista.
Ver video

• Se tiene la siguiente lista:

• lista=[[4,12,5,66], [14,6,25], [3,4,5,67,89,23,1], [78,56]]

Imprimir la lista. Luego fijar con el valor cero todos los elementos
mayores a 10 contenidos en todos los elementos de la variable "lista".
Volver a imprimir la lista.
Ver video

• Crear una lista por asignación con la cantidad de elementos de tipo lista
que usted desee. Luego imprimir el último elemento de la lista principal.
Ver video
Solución

Retornar

21 - Listas: carga por teclado de


componentes de tipo lista
En el concepto anterior vimos que fácilmente podemos definir por asignación
una lista cuyas componentes sean también listas:

lista=[[1,2,3], [7,4], [9,2]]

En muchas situaciones debemos crear una nueva lista ingresando los datos
por teclado o por operaciones del mismo programa.

Problema 1:
Crear y cargar una lista con los nombres de tres alumnos. Cada alumno tiene
dos notas, almacenar las notas en una lista paralela. Cada componente de la
lista paralela debe ser también una lista con las dos notas. Imprimir luego cada
nombre y sus dos notas.
Si cargáramos los datos por asignación sería algo parecido a esto:

alumnos=["juan", "ana", "luis"]


notas=[[10,8], [6,5], [2,8]]

En la componente 0 de la lista alumnos tenemos almacenado el nombre "juan"


y como son listas paralelas en la componente 0 de la lista notas tenemos
almacenado una lista con las dos notas 10 y 8.
Nuestro objetivo como lo pide el problema es cargar los datos por teclado.
Programa: ejercicio101.py
Ver video

nombres=[]
notas=[]
for x in range(3):
nom=input("Ingrese el nombre del alumno:")
nombres.append(nom)
no1=int(input("Ingrese la primer nota:"))
no2=int(input("Ingrese la segunda nota:"))
notas.append([no1,no2])

for x in range(3):
print(nombres[x],notas[x][0],notas[x][1])
La ejecución del programa tiene una salida por pantalla similar a:
La creación de las dos listas no difiere una de otra:

nombres=[]
notas=[]

En la estructura repetitiva for procedemos a cargar un nombre y agregarlo a la


lista en forma similar como lo hemos hecho en conceptos anteriores:

for x in range(3):
nom=input("Ingrese el nombre del alumno:")
nombres.append(nom)
Lo nuevo se presenta cuando queremos añadir elementos a la lista notas, lo
hacemos con el mismo método append pero le pasamos como parámetro una
lista con dos elementos:

no1=int(input("Ingrese la primer nota:"))


no2=int(input("Ingrese la segunda nota:"))
notas.append([no1,no2])

Cuando imprimimos el nombre lo accedemos por un solo subíndice, pero para


acceder a cada una de las notas debemos indicar dos subíndices, el primer
subíndice es con respecto a que elemento accedemos de la lista principal y el
segundo subíndice hace referencia a la lista contenida en dicha componente:

for x in range(3):
print(nombres[x],notas[x][0],notas[x][1])

Problema 2:
Se tiene que cargar la siguiente información:
· Nombres de 3 empleados
· Ingresos en concepto de sueldo, cobrado por cada empleado, en los últimos 3
meses.
Confeccionar el programa para:
a) Realizar la carga de los nombres de empleados y los tres sueldos por cada
empleado.
b) Generar una lista que contenga el ingreso acumulado en sueldos en los
últimos 3 meses para cada empleado.
c) Mostrar por pantalla el total pagado en sueldos a cada empleado en los
últimos 3 meses
d) Obtener el nombre del empleado que tuvo el mayor ingreso acumulado
En este problema definiremos tres listas:
Una lista para almacenar los nombres de los empleados, por ejemplo si lo
cargamos por asignación:

nombres=["juan", "ana", "luis"]

Una lista paralela a la anterior para almacenar los sueldos en los últimos tres
meses por cada empleado:

sueldos=[[5000,5100,5000], [7000,6500,6000], [2500,2500,2500]]


Otra lista paralela donde almacenamos el total de sueldos cobrados por cada
empleado que resulta de sumar los tres sueldos de cada empleado contenidos
en la lista sueldos:

totalsueldos=[15100, 19500, 7500]

Es importante notar que estos datos no los cargaremos por asignación sino los
cargaremos por teclado a las dos primeras listas y la tercera la generaremos
extrayendo los datos de la lista sueldos.
Programa: ejercicio102.py
Ver video

nombres=[]
sueldos=[]
totalsueldos=[]

for x in range(3):
nom=input("Ingrese el nombre del empleado:")
nombres.append(nom)
su1=int(input("Ingrese el primer sueldo:"))
su2=int(input("Ingrese el segundo sueldo:"))
su3=int(input("Ingrese el tercer sueldo:"))
sueldos.append([su1, su2, su3])

for x in range(3):
total=sueldos[x][0]+sueldos[x][1]+sueldos[x][
2]
totalsueldos.append(total)

for x in range(3):
print(nombres[x], totalsueldos[x])
posmayor=0
mayor=totalsueldos[0]
for x in range(1,3):
if totalsueldos[x]>mayor:
mayor=totalsueldos[x]
posmayor=x
print("Empleado con mayores ingresos en los ultim
os tres meses")
print(nombres[posmayor])
print("con un ingreso de",mayor)
Definimos 3 listas:

nombres=[]
sueldos=[]
totalsueldos=[]

En el primer for realizamos la carga de cada nombre de empleado y sus tres


últimos sueldos, en la lista nombres añadimos strings y en la lista sueldos
añadimos otra lista con tres enteros que representan los sueldos:

for x in range(3):
nom=input("Ingrese el nombre del empleado:")
nombres.append(nom)
su1=int(input("Ingrese el primer sueldo:"))
su2=int(input("Ingrese el segundo sueldo:"))
su3=int(input("Ingrese el tercer sueldo:"))
sueldos.append([su1, su2, su3])

En el segundo ciclo repetitivo generamos automáticamente la lista totalsueldos


(es decir no cargamos por teclado), este valor resulta de sumar los tres sueldos
de cada empleado que se encuentran en cada una de las listas contenidas en
la lista sueldos:

for x in range(3):
total=sueldos[x][0]+sueldos[x][1]+sueldos[x][2]
totalsueldos.append(total)

Imprimimos ahora el nombre del empleado seguido por el ingreso total en


sueldos de los últimos tres meses:

for x in range(3):
print(nombres[x], totalsueldos[x])

Finalmente el problema requiere mostrar el nombre del empleado que recaudó


más en sueldos en los últimos tres meses.
Iniciamos dos variables previas al for indicando en una la posición de importe
en sueldos mayor y en otra dicho importe. Hacemos la suposición antes de
ingresar al for que el mayor está en la posición 0:

posmayor=0
mayor=totalsueldos[0]

Disponemos un for cuya variable se inicia en 1 y dentro del for controlamos el


importe del total de sueldos si supera al que hemos considerado mayor hasta
ese momento "mayor" procedemos a actualizar las dos variables: mayor y
posmayor:

for x in range(1,3):
if totalsueldos[x]>mayor:
mayor=totalsueldos[x]
posmayor=x

Finalmente cuando salimos del ciclo procedemos a mostrar el nombre del


empleado que recaudó más en los últimos tres meses:

print("Empleado con mayores ingresos en los ultimos tres meses")


print(nombres[posmayor])
print("con un ingreso de",mayor)

Problema 3:
Solicitar por teclado dos enteros. El primer valor indica la cantidad de
elementos que crearemos en la lista. El segundo valor indica la cantidad de
elementos que tendrá cada una de las listas internas a la lista principal.
Mostrar la lista y la suma de todos sus elementos.
Por ejemplo si el operador carga un 2 y un 4 significa que debemos crear una
lista similar a:

lista=[[1,1,1,1], [1,1,1,1]]

Programa: ejercicio103.py
Ver video

lista=[]
elementos=int(input("Cuantos elementos tendra la
lista:"))
sub=int(input("Cuantos elementos tendran las list
as internas:"))
for k in range(elementos):
lista.append([])
for x in range(sub):
valor=int(input("Ingrese valor:"))
lista[k].append(valor)

print(lista)

suma=0
for k in range(len(lista)):
for x in range(len(lista[k])):
suma=suma+lista[k][x]

print("La suma de todos sus elementos:",suma)


Lo primero que hacemos en este problema además de definir la lista es cargar
dos enteros por teclado:

lista=[]
elementos=int(input("Cuantos elementos tendra la lista:"))
sub=int(input("Cuantos elementos tendran las listas internas:"))

El primer for se repetirá tantas veces como indica el primer valor ingresado por
teclado almacenado en la variable "elementos", cada vuelta de este for se crea
un elemento en la "lista" y se carga una lista vacía []:

for k in range(elementos):
lista.append([])

En el for interior procedemos a cargar tantos valores como lo indicamos en la


variable "sub" y los vamos añadiendo en la lista vacía que creamos antes de
este for:

for x in range(sub):
valor=int(input("Ingrese valor:"))
lista[k].append(valor)

Finalmente para sumar todos los elementos enteros almacenados en "lista"


debemos disponer estructuras repetitivas anidadas:

suma=0
for k in range(len(lista)):
for x in range(len(lista[k])):
suma=suma+lista[k][x]

El for de las "k" se repite tantas veces como elementos tenga "lista" y el for de
las x se repite tantas veces como elementos tenga la lista en la posición k.
Problema 4:
Definir dos listas de 3 elementos.
La primer lista cada elemento es una sublista con el nombre del padre y la
madre de una familia.
La segunda lista está constituida por listas con los nombres de los hijos de
cada familia. Puede haber familias sin hijos.
Imprimir los nombres del padre, la madre y sus hijos.
También imprimir solo el nombre del padre y la cantidad de hijos que tiene
dicho padre.
Un ejemplo si se define por asignación:

padres=[["juan","ana"], ["carlos","maria"], ["pedro","laura"]]


hijos=[["marcos","alberto","silvia"], [], ["oscar"]]

Como son listas paralelas podemos decir que la familia cuyos padres son
"juan" y "ana" tiene tres hijos llamados "marcos", "alberto", "silvia". La segunda
familia no tiene hijos y la tercera tiene solo uno.
Programa: ejercicio104.py
Ver video

padres=[]
hijos=[]
for k in range(3):
pa=input("Ingrese el nombre del padre:")
ma=input("Ingrese el nombre de la madre:")
padres.append([pa, ma])
cant=int(input("Cuantos hijos tienen esta fam
ilia:"))
hijos.append([])
for x in range(cant):
nom=input("Ingrese el nombre del hijo:")
hijos[k].append(nom)

print("Listado del padre, madre y sus hijos")


for k in range(3):
print("Padre:",padres[k][0])
print("Madre:",padres[k][1])
for x in range(len(hijos[k])):
print("Hijo:",hijos[k][x])
print("Listado del padre y cantidad de hijos que
tiene")
for x in range(3):
print("padre:",padres[x][0])
print("Cantidad de hijos:",len(hijos[x]))
Comenzamos definiendo las dos listas:

padres=[]
hijos=[]

El primer for es para cargar y crear cada elemento de la lista "padres", crear
una elemento de la lista hijos con una lista vacía y solicitar que se cargue
cuantos hijos tiene la familia:

for k in range(3):
pa=input("Ingrese el nombre del padre:")
ma=input("Ingrese el nombre de la madre:")
padres.append([pa, ma])
cant=int(input("Cuantos hijos tienen esta familia:"))
hijos.append([])

El for interno se ingresan los nombres de los hijos y se agregan a la lista hijos
en la posición respectiva. El for interno puede llegar a no ejecutarse si se
ingresa un 0 en cantidad de hijos:

for x in range(cant):
nom=input("Ingrese el nombre del hijo:")
hijos[k].append(nom)

Para imprimir los nombres de ambos padres y sus hijos también


implementamos un for anidado:

print("Listado del padre, madre y sus hijos")


for k in range(3):
print("Padre:",padres[k][0])
print("Madre:",padres[k][1])
for x in range(len(hijos[k])):
print("Hijo:",hijos[k][x])

Para mostrar la cantidad de hijos que tiene un determinado padre llamamos a


la función len de cada una de las sublistas contenidas en la lista hijos:

print("Listado del padre y cantidad de hijos que tiene")


for x in range(3):
print("padre:",padres[x][0])
print("Cantidad de hijos:",len(hijos[x]))

Problemas propuestos
• Se desea saber la temperatura media trimestral de cuatro paises. Para
ello se tiene como dato las temperaturas medias mensuales de dichos
paises.
Se debe ingresar el nombre del país y seguidamente las tres
temperaturas medias mensuales.
Seleccionar las estructuras de datos adecuadas para el almacenamiento
de los datos en memoria.
a - Cargar por teclado los nombres de los paises y las temperaturas
medias mensuales.
b - Imprimir los nombres de las paises y las temperaturas medias
mensuales de las mismas.
c - Calcular la temperatura media trimestral de cada país.
c - Imprimir los nombres de los paises y las temperaturas medias
trimestrales.
b - Imprimir el nombre del pais con la temperatura media trimestral
mayor.

Ver video

• Definir una lista y almacenar los nombres de 3 empleados.


Por otro lado definir otra lista y almacenar en cada elemento una sublista
con los números de días del mes que el empleado faltó.
Imprimir los nombres de empleados y los días que faltó.
Mostrar los empleados con la cantidad de inasistencias.
Finalmente mostrar el nombre o los nombres de empleados que faltaron
menos días.

Ver video
• Desarrollar un programa que cree una lista de 50 elementos. El primer
elemento es una lista con un elemento entero, el segundo elemento es
una lista de dos elementos etc.
La lista debería tener esta estructura y asignarle esos valores a medida
que se crean los elementos:

• [[1], [1,2], [1,2,3], [1,2,3,4], [1,2,3,4,5], etc....]

Ver video
Solución

Retornar

22 - Listas: eliminación de elementos


Hemos visto que una lista la podemos iniciar por asignación indicando sus
elementos.

lista=[10, 20, 30, 40]

También podemos agregarle elementos al final mediante el método append:

lista.append(120)

Si ahora imprimimos la lista tenemos como resultado:

[10, 20, 30, 40, 120]

Otra característica fundamental de las listas en Python es que podemos


eliminar cualquiera de sus componentes llamando al método pop e indicando la
posición del elemento a borrar:

lista.pop(0)

Ahora si imprimimos la lista luego de eliminar el primer elemento el resultado


es:

[20, 30, 40, 120]


Otra cosa que hay que hacer notar que cuando un elemento de la lista se
elimina no queda una posición vacía, sino se desplazan todos los elementos de
la derecha una posición.
El método pop retorna el valor almacenado en la lista en la posición indicada,
aparte de borrarlo.

lista=[10, 20, 30, 40]


print(lista.pop(0)) # imprime un 10

Problema 1:
Crear una lista por asignación con 5 enteros. Eliminar el primero, el tercero y el
último de la lista.
Programa: ejercicio108.py
Ver video

lista=[10, 20, 30, 40, 50]

print(lista)

lista.pop(0)
lista.pop(1)
lista.pop(2)

print(lista)
Parecería que con esas tres llamadas al método pop se eliminan los tres
primeros elementos pero no es así, si imprimimos cada vez que borramos uno
veremos que estamos borrando el primero, tercero y quinto.

lista=[10, 20, 30, 40, 50]


print(lista)
# se imprime [10, 20, 30, 40, 50]
lista.pop(0)
print(lista)
# se imprime [20, 30, 40, 50]
lista.pop(1)
print(lista)
# se imprime [20, 40, 50]
lista.pop(2)
# se imprime [20, 40]
print(lista)

Problema 2:
Crear una lista y almacenar 10 enteros pedidos por teclado. Eliminar todos los
elementos que sean iguales al número entero 5.
Programa: ejercicio109.py
Ver video

lista=[]
for x in range(10):
valor=int(input("Ingrese valor:"))
lista.append(valor)

print(lista)

posicion=0
while posicion<len(lista):
if lista[posicion]==5:
lista.pop(posicion)
else:
posicion=posicion+1

print(lista)
Mediante un for cargamos 10 elementos en la lista:

lista=[]
for x in range(10):
valor=int(input("Ingrese valor:"))
lista.append(valor)

Como es posible que se eliminen 0, 1, 2 etc. elementos de la lista utilizamos un


ciclo while (no podemos usar un for, ya que el contador del mismo no indicará
correctamente el subindice a analizar)
Llevamos un contador llamado "posicion" que nos indica que elemento de la
lista estamos verificando en el if, en el caso que se debe borrar llamamos al
método pop pasando el contador y no incrementamos en uno el contador
"posicion" ya que los elementos de la derecha se desplazan una posición a
izquierda.
En el caso que no se debe borrar se incrementa en uno el contador "posicion"
para analizar el siguiente elemento de la lista en la próxima vuelta del ciclo:

posicion=0
while posicion<len(lista):
if lista[posicion]==5:
lista.pop(posicion)
else:
posicion=posicion+1

Si ejecutamos y cargamos tres cincos en distintas posiciones de la lista


tenemos como resultado:
Acotación: otra forma de eliminar elementos de una lista
Para eliminar elementos de una lista también es empleada la función "del"
pasando como parámetro la referencia de la componente a eliminar:

lista=[10, 20, 30, 40, 50]


print(lista)

del(lista[0])
del(lista[1])
del(lista[2])

print(lista) # 20 40

Problemas propuestos
• Crear dos listas paralelas. En la primera ingresar los nombres de
empleados y en la segunda los sueldos de cada empleado.
Ingresar por teclado cuando inicia el programa la cantidad de empleados
de la empresa.
Borrar luego todos los empleados que tienen un sueldo mayor a 10000
(tanto el sueldo como su nombre)

Ver video

• Crear una lista de 5 enteros y cargarlos por teclado. Borrar los


elementos mayores o iguales a 10 y generar una nueva lista con dichos
valores.

Ver video
Solución

Retornar
23 - Concepto de funciones -
Programación estructurada
Hasta ahora hemos trabajado con una metodología de programación lineal.
Todas las instrucciones de nuestro archivo *.py se ejecutan en forma
secuencial de principio a fin.
Esta forma de organizar un programa solo puede ser llevado a cabo si el
mismo es muy pequeño (decenas de líneas)
Cuando los problemas a resolver tienden a ser más grandes la metodología de
programación lineal se vuelve ineficiente y compleja.
El segundo paradigma de programación que veremos es la programación
estructurada.
La programación estructurada busca dividir o descomponer un problema
complejo en pequeños problemas. La solución de cada uno de esos pequeños
problemas nos trae la solución del problema complejo.
En Python el planteo de esas pequeñas soluciones al problema complejo se
hace dividiendo el programa en funciones.
Una función es un conjunto de instrucciones en Python que resuelven un
problema específico.
El lenguaje Python ya tiene incorporada algunas funciones básicas. Algunas de
ellas ya las utilizamos en conceptos anteriores como son las funciones: print,
len y range.
Veamos ahora como crear nuestras propias funciones.
El tema de funciones en un principio puede presentar dificultades para
entenderlo y ver sus ventajas ante la metodología de programación lineal que
veníamos trabajando en conceptos anteriores.
Los primeros problemas que presentaremos nos puede parecer que sea más
conveniente utilizar programación lineal en vez de programación estructurada
por funciones.
A medida que avancemos veremos que si un programa empieza a ser más
complejo (cientos de líneas, miles de líneas o más) la división en pequeñas
funciones nos permitirá tener un programa más ordenado y fácil de entender y
por lo tanto en mantener.

Problema 1:
Confeccionar una aplicación que muestre una presentación en pantalla del
programa. Solicite la carga de dos valores y nos muestre la suma. Mostrar
finalmente un mensaje de despedida del programa.
Implementar estas actividades en tres funciones.
Programa: ejercicio112.py
Ver video

def presentacion():
print("Programa que permite cargar dos valore
s por teclado.")
print("Efectua la suma de los valores")
print("Muestra el resultado de la suma")
print("*******************************")

def carga_suma():
valor1=int(input("Ingrese el primer valor:"))
valor2=int(input("Ingrese el segundo valor:")
)
suma=valor1+valor2
print("La suma de los dos valores es:",suma)

def finalizacion():
print("*******************************")
print("Gracias por utilizar este programa")

# programa principal
presentacion()
carga_suma()
finalizacion()
La forma de organizar nuestro programa cambia en forma radical.
El programa ahora no empieza a ejecutarse en la línea 1.
El programa principal comienza a ejecutarse luego del comentario "programa
principal":

# programa principal

presentacion()
carga_suma()
finalizacion()

Primero declaramos las tres funciones llamadas presentacion, carga_suma y


finalizacion.
La sintaxis para declarar una función es mediante la palabra clave def seguida
por el nombre de la función (el nombre de la función no puede tener espacios
en blanco, comenzar con un número y el único caracter especial permitido es
el _ )
Luego del nombre de la función deben ir entre paréntesis los datos que llegan,
si no llegan datos como es el caso de nuestras tres funciones solo se disponen
paréntesis abierto y cerrado. Al final disponemos los :
Todo el bloque de la función se indenta cuatro espacios como venimos
trabajando cuando definimos estructuras condicionales o repetitivas.
Dentro de una función implementamos el algoritmo que pretendemos que
resuelva esa función, por ejemplo la función presentacion tiene por objetivo
mostrar en pantalla el objetivo del programa:

def presentacion():
print("Programa que permite cargar dos valores por teclado.")
print("Efectua la suma de los valores")
print("Muestra el resultado de la suma")
print("*******************************")

La función carga_suma() permite ingresar dos enteros por teclado, sumarlos y


mostrarlos en pantalla:

def carga_suma():
valor1=int(input("Ingrese el primer valor:"))
valor2=int(input("Ingrese el segundo valor:"))
suma=valor1+valor2
print("La suma de los dos valores es:",suma)

La función finalizacion() tiene por objetivo mostrar un mensaje que muestre al


operador que el programa finalizó:

def finalizacion():
print("*******************************")
print("Gracias por utilizar este programa")

Luego de definir las funciones tenemos al final de nuestro archivo *.py las
llamadas de las funciones:

# programa principal

presentacion()
carga_suma()
finalizacion()

Si no hacemos las llamadas a las funciones los algoritmos que implementan las
funciones nunca se ejecutarán.
Cuando en el bloque del programa principal se llama una función hasta que no
finalice no continua con la llamada a la siguiente función:

# programa principal

presentacion() # se ejecutan las cuatro líneas que contiene la función presenta


cion y recién continúa con la próxima línea.
El orden en que llamamos a las funciones es muy importante. Supongamos
que nuestro bloque del programa principal llamamos las funciones en este
orden:

# programa principal
finalizacion()
carga_suma()
presentacion()

Veremos que primero muestra el mensaje de finalización, luego la carga y


suma de datos y finalmente aparece por pantalla los mensajes de presentación
de nuestro programa.
Yo se que en principio al ser un problema tan sencillo y que venimos de
resolver muchos programas con la metodología de programación lineal nos
parecer mas fácil implementar este programa con la sintaxis:

print("Programa que permite cargar dos valores por teclado.")


print("Efectua la suma de los valores")
print("Muestra el resultado de la suma")
print("*******************************")

valor1=int(input("Ingrese el primer valor:"))


valor2=int(input("Ingrese el segundo valor:"))
suma=valor1+valor2
print("La suma de los dos valores es:",suma)

print("*******************************")
print("Gracias por utilizar este programa")

Tengamos un poco de paciencia para aprender la nueva sintaxis de dividir un


programa en funciones, imagina que las soluciones a problemas complejos
pueden requerir miles de líneas y un planteo secuencial será muy difícil.

Problema 2:
Confeccionar una aplicación que solicite la carga de dos valores enteros y
muestre su suma.
Repetir la carga e impresion de la suma 5 veces.
Mostrar una línea separadora después de cada vez que cargamos dos valores
y su suma.
Programa: ejercicio113.py
Ver video

def carga_suma():
valor1=int(input("Ingrese el primer valor:"))
valor2=int(input("Ingrese el segundo valor:")
)
suma=valor1+valor2
print("La suma de los dos valores es:",suma)

def separacion():
print("*******************************")

# programa principal

for x in range(5):
carga_suma()
separacion()
Hemos declarado dos funciones, una que permite cargar dos enteros sumarlos
y mostrar el resultado:

def carga_suma():
valor1=int(input("Ingrese el primer valor:"))
valor2=int(input("Ingrese el segundo valor:"))
suma=valor1+valor2
print("La suma de los dos valores es:",suma)

Y otra función que tiene por objetivo mostrar una línea separadora con
asteriscos:

def separacion():
print("*******************************")

Ahora nuestro bloque principal del programa, recordemos que estas líneas son
las primeras que se ejecutarán cuando iniciemos el programa:

# programa principal

for x in range(5):
carga_suma()
separacion()

Como vemos podemos llamar a la función carga_suma() y separación()


muchas veces en nuestro caso en particular 5 veces.
Lo nuevo que debe quedar claro es que la llamada a las funciones desde el
bloque principal de nuestro programa puede hacerse múltiples veces (esto es
lógico, recordemos que print es una función ya creada en Python y la llamamos
múltiples veces dentro de nuestro algoritmo)

Problemas propuestos
• Desarrollar un programa con dos funciones. La primer solicite el ingreso
de un entero y muestre el cuadrado de dicho valor. La segunda que
solicite la carga de dos valores y muestre el producto de los mismos.
LLamar desde el bloque del programa principal a ambas funciones.

Ver video

• Desarrollar un programa que solicite la carga de tres valores y muestre


el menor. Desde el bloque principal del programa llamar 2 veces a dicha
función (sin utilizar una estructura repetitiva)

Ver video
Solución

Retornar

24 - Funciones: parámetros
Vimos en el concepto anterior que una función resuelve una parte de nuestro
algoritmo.
Tenemos por un lado la declaración de la función por medio de un nombre y el
algoritmo de la función seguidamente. Luego para que se ejecute la función la
llamamos desde el bloque principal de nuestro programa.
Ahora veremos que una función puede tener parámetros para recibir datos. Los
parámetros nos permiten comunicarle algo a la función y la hace más flexible.

Problema 1:
Confeccionar una aplicación que muestre una presentación en pantalla del
programa. Solicite la carga de dos valores y nos muestre la suma. Mostrar
finalmente un mensaje de despedida del programa.
Programa: ejercicio116.py
Ver video

def mostrar_mensaje(mensaje):
print("**************************************
***********")
print(mensaje)
print("**************************************
***********")

def carga_suma():
valor1=int(input("Ingrese el primer valor:"))
valor2=int(input("Ingrese el segundo valor:")
)
suma=valor1+valor2
print("La suma de los dos valores es:",suma)

# programa principal

mostrar_mensaje("El programa calcula la suma de d


os valores ingresados por teclado.")
carga_suma()
mostrar_mensaje("Gracias por utilizar este progra
ma")
Ahora para resolver este pequeño problema hemos planteado una función
llamada mostrar_mensaje que recibe como parámetro un string (cadena de
caracteres) y lo muestra en pantalla.
Los parámetros van seguidos del nombre de la función encerrados entre
paréntesis (y en el caso de tener más de un parámetro los mismos deben ir
separados por coma):

def mostrar_mensaje(mensaje):
print("*************************************************")
print(mensaje)
print("*************************************************")

Un parámetro podemos imaginarlo como una variable que solo se puede


utilizar dentro de la función.
Ahora cuando llamamos a la función mostrar_mensaje desde el bloque
principal de nuestro programa debemos pasar una variable string o un valor de
tipo string:

mostrar_mensaje("El programa calcula la suma de dos valores ingresados por tecla


do.")

El string que le pasamos: "El programa calcula la suma de dos valores


ingresados por teclado." lo recibe el parámetro de la función.
Una función con parámetros nos hace más flexible la misma para utilizarla en
distintas circunstancias. En nuestro problema la función mostrar_mensaje la
utilizamos tanto para la presentación inicial de nuestro programa como para
mostrar el mensaje de despedida. Si no existieran los parámetros estaríamos
obligados a implementar dos funciones como el concepto anterior.

Problema 2:
Confeccionar una función que reciba tres enteros y nos muestre el mayor de
ellos. La carga de los valores hacerlo por teclado.
Programa: ejercicio117.py
Ver video

def mostrar_mayor(v1,v2,v3):
print("El valor mayor de los tres numeros es"
)
if v1>v2 and v1>v3:
print(v1)
else:
if v2>v3:
print(v2)
else:
print(v3)
def cargar():
valor1=int(input("Ingrese el primer valor:"))
valor2=int(input("Ingrese el segundo valor:")
)
valor3=int(input("Ingrese el tercer valor:"))
mostrar_mayor(valor1,valor2,valor3)

# programa principal

cargar()
Es importante notar que un programa en Python no ejecuta en forma lineal las
funciones definidas en el archivo *.py sino que arranca en la zona del bloque
principal. En nuestro ejemplo se llama primero a la función "cargar()", esta
función no tiene parámetros.
La función cargar solicita el ingreso de tres enteros por teclado y llama a la
función mostrar_mayor y le pasa a sus parámetros las tres variable enteras
valor1, valor2 y valor3.
La función mostrar_mayor recibe en sus parámetros v1, v2 y v3 los valores
cargados en las variables valor1, valor2 y valor3.
Los parámetros son la forma que nos permite comunicar la función cargar con
la función mostrar_mayor.
Dentro de la función mostrar_mayor no podemos acceder a las variable valor1,
valor2 y valor3 ya que son variables locales de la función cargar.
La definición mostrar_mayor debe estar escrita antes de la definición de la
función cargar que es donde la llamamos.
Otra cosa importante notar que en la sección del programa principal solo
llamamos a la función cargar, es decir que en esta zona no es obligatorio
llamar a cada una de las funciones que definimos.
Problema 3:
Desarrollar un programa que permita ingresar el lado de un cuadrado. Luego
preguntar si quiere calcular y mostrar su perímetro o su superficie.
Programa: ejercicio118.py
Ver video

def mostrar_perimetro(lado):
per=lado*4
print("El perimetro es",per)

def mostrar_superficie(lado):
sup=lado*lado
print("La superficie es",sup)

def cargar_dato():
la=int(input("Ingrese el valor del lado de un
cuadrado:"))
respuesta=input("Quiere calcular el perimetro
o la superficie[ingresar texto: perimetro/superfi
cie]?")
if respuesta=="perimetro":
mostrar_perimetro(la)
if respuesta=="superficie":
mostrar_superficie(la)

# programa principal
cargar_dato()
Definimos dos funciones que calculan y muestran el perimetro por un lado y
por otro la superficie:

def mostrar_perimetro(lado):
per=lado*4
print("El perimetro es",per)

def mostrar_superficie(lado):
sup=lado*lado
print("La superficie es",sup)

La tercer función permite cargar el lado del cuadrado e ingresar un string que
indica que cálculo deseamos realizar si obtener el perímetro o la superficie.
Una vez que se ingreso la variable respuesta procedemos a llamar a la función
que efectúa el calculo respectivo pasando como dato la variable local "la" que
almacena el valor del lado del cuadrado.
Los parámetros son la herramienta fundamental para pasar datos cuando
hacemos la llamada a una función.

Problemas propuestos
• Desarrollar una funcion que reciba un string como parametro y nos
muestre la cantidad de vocales. Llamarla desde el bloque principal del
programa 3 veces con string distintos.

Ver video

• Confeccionar una función que reciba tres enteros y los muestre


ordenados de menor a mayor. En otra función solicitar la carga de 3
enteros por teclado y proceder a llamar a la primer función definida.

Ver video
Solución

Retornar
25 - Funciones: retorno de datos
Hemos comenzado a pensar con la metodología de programación
estructurada. Buscamos dividir un problema en subproblemas y plantear
algoritmos en Python que los resuelvan.
Vimos que una función la definimos mediante un nombre y que puede recibir
datos por medio de sus parámetros.
Los parámetros son la forma para que una función reciba datos para ser
procesados. Ahora veremos otra característica de las funciones que es la de
devolver un dato a quien invocó la función (recordemos que una función la
podemos llamar desde el bloque principal de nuestro programa o desde otra
función que desarrollemos)

Problema 1:
Confeccionar una función que le enviemos como parámetro el valor del lado de
un cuadrado y nos retorne su superficie.
Programa: ejercicio120.py
Ver video

def retornar_superficie(lado):
sup=lado*lado
return sup

# bloque principal del programa

va=int(input("Ingrese el valor del lado del cuafr


ado:"))
superficie=retornar_superficie(va)
print("La superficie del cuadrado es",superficie)
Aparece una nueva palabra clave en Python para indicar el valor devuelto por
la función: return
La función retornar_superficie recibe un parámetro llamado lado, definimos una
variable local llamada sup donde almacenamos el producto del parámetro lado
por sí mismo.
La variable local sup es la que retorna la función mediante la palabra clave
return:

def retornar_superficie(lado):
sup=lado*lado
return sup

Hay que tener en cuenta que las variables locales (en este caso sup) solo se
pueden consultar y modificar dentro de la función donde se las define, no se
tienen acceso a las mismas en el bloque principal del programa o dentro de
otra función.
Hay un cambio importante cuando llamamos o invocamos a una función que
devuelve un dato:

superficie=retornar_superficie(va)

Es decir el valor devuelto por la función retornar_superficie se almacena en la


variable superficie.
Es un error lógico llamar a la función retornar_superficie y no asignar el valor a
una variable:

retornar_superficie(va)

El dato devuelto (en nuestro caso la superficie del cuadrado) no se almacena.


Si podemos utilizar el valor devuelto para pasarlo a otra función:

va=int(input("Ingrese el valor del lado del cuafrado:"))


print("La superficie del cuadrado es",retornar_superficie(va))

La función retornar_superficie devuelve un entero y se lo pasamos a la función


print para que lo muestre.

Problema 2:
Confeccionar una función que le enviemos como parámetros dos enteros y nos
retorne el mayor.
Programa: ejercicio121.py
Ver video
def retornar_mayor(v1,v2):
if v1>v2:
mayor=v1
else:
mayor=v2
return mayor

# bloque principal
valor1=int(input("Ingrese el primer valor:"))
valor2=int(input("Ingrese el segundo valor:"))
print(retornar_mayor(valor1,valor2))
Nuevamente tenemos una función que recibe dos parámetros y retorna el
mayor de ellos:

def retornar_mayor(v1,v2):
if v1>v2:
mayor=v1
else:
mayor=v2
return mayor

Si queremos podemos hacerla más sintética a esta función sin tener que
guardar en una variable local el valor a retornar:

def retornar_mayor(v1,v2):
if v1>v2:
return v1
else:
return v2
Cuando una función encuentra la palabra return no sigue ejecutando el resto
de la función sino que sale a la línea del programa desde donde llamamos a
dicha función.

Problema 3:
Confeccionar una función que le enviemos como parámetro un string y nos
retorne la cantidad de caracteres que tiene. En el bloque principal solicitar la
carga de dos nombres por teclado y llamar a la función dos veces. Imprimir en
el bloque principal cual de las dos palabras tiene más caracteres.
Programa: ejercicio122.py
Ver video

def largo(cadena):
return len(cadena)

# bloque principal

nombre1=input("Ingrese primer nombre:")


nombre2=input("Ingrese segundo nombre:")
la1=largo(nombre1)
la2=largo(nombre2)
if la1==la2:
print("Los nombres:",nombre1,nombre2,"tienen
la misma cantidad de caracteres")
else:
if la1>la2:
print(nombre1,"es mas largo")
else:
print(nombre2,"es mas largo")
Hemos definido una función llamada largo que recibe un parámetro llamado
cadena y retorna la cantidad de caracteres que tiene dicha cadena (utilizamos
la función len para obtener la cantidad de caracteres)
El lenguaje Python ya tiene una función que retorna la cantidad de caracteres
de un string: len, nosotros hemos creado una que hace lo mismo pero tiene un
nombre en castellano: largo.
Desde el bloque principal de nuestro programa llamamos a la función largo
pasando primero un string y guardando en una variable el entero devuelto:

la1=largo(nombre1)

En forma similar calculamos el largo del segundo nombre:

la2=largo(nombre2)

Solo nos queda analizar cual de las dos variables tiene un valor mayor para
indicar cual tiene más caracteres:

if la1==la2:
print("Los nombres:",nombre1,nombre2,"tienen la misma cantidad de caracteres
")
else:
if la1>la2:
print(nombre1,"es mas largo")
else:
print(nombre2,"es mas largo")

Problemas propuestos
• Elaborar una función que reciba tres enteros y nos retorne el valor
promedio de los mismos.

Ver video

• Elaborar una función que nos retorne el perímetro de un cuadrado


pasando como parámetros el valor de un lado.

Ver video
• Confeccionar una función que calcule la superficie de un rectángulo y la
retorne, la función recibe como parámetros los valores de dos de sus
lados:

• def retornar_superficie(lado1,lado2):

En el bloque principal del programa cargar los lados de dos rectángulos


y luego mostrar cual de los dos tiene una superficie mayor.
Ver video

• Plantear una función que reciba un string en mayúsculas o minúsculas y


retorne la cantidad de letras 'a' o 'A'.

Ver video
Solución

Retornar

26 - Funciones: parámetros de tipo


lista
Hemos visto que si trabajamos con programación estructurada debemos dividir
nuestro problema en trocitos y plantear algoritmos que resuelvan cada uno de
los trozos.
La división en Python se hace implementando funciones. La comunicación
entre estas funciones se produce mediante el envío de datos a través de los
parámetros y el valor que retorna la función.
Hasta ahora hemos resuelto problemas enviando datos simples como enteros,
float y cadenas de caracteres. En este concepto veremos que una función
puede recibir tanto datos simples como estructuras de datos.
La estructura de datos vista hasta este momento y que podemos enviarle a una
función es la lista.

Problema 1:
Definir por asignación una lista de enteros en el bloque principal del programa.
Elaborar tres funciones, la primera recibe la lista y retorna la suma de todos sus
elementos, la segunda recibe la lista y retorna el mayor valor y la última recibe
la lista y retorna el menor.
Programa: ejercicio127.py
Ver video

def sumarizar(lista):
suma=0
for x in range(len(lista)):
suma=suma+lista[x]
return suma

def mayor(lista):
may=lista[0]
for x in range(1,len(lista)):
if lista[x]>may:
may=lista[x]
return may

def menor(lista):
men=lista[0]
for x in range(1,len(lista)):
if lista[x]<men:
men=lista[x]
return men
# bloque principal del programa

listavalores=[10, 56, 23, 120, 94]


print("La lista completa es")
print(listavalores)
print("La suma de todos su elementos es", sumariz
ar(listavalores))
print("El mayor valor de la lista es", mayor(list
avalores))
print("El menor valor de la lista es", menor(list
avalores))
La función sumarizar recibe un parámetro de tipo lista, dentro de la misma lo
recorremos mediante un for y accedemos a sus elementos por medio de un
subíndice:

def sumarizar(lista):
suma=0
for x in range(len(lista)):
suma=suma+lista[x]
return suma

Desde el bloque principal de nuestro programa llamamos a sumarizar enviando


el dato retornado a la función print para que lo muestre:

print("La suma de todos su elementos es", sumarizar(listavalores))

De forma similar definimos las otras dos funciones que también reciben la lista
y luego implementan los algoritmos para identificar el mayor y el menor de la
lista:

def mayor(lista):
may=lista[0]
for x in range(1,len(lista)):
if lista[x]>may:
may=lista[x]
return may

def menor(lista):
men=lista[0]
for x in range(1,len(lista)):
if lista[x]<men:
men=lista[x]
return men

Las llamadas a estas dos funciones desde el bloque principal es similar a


cuando llamamos a sumarizar (como cada una retorna un entero procedemos
a llamarlas dentro de la función print):

print("El mayor valor de la lista es", mayor(listavalores))


print("El menor valor de la lista es", menor(listavalores))

El nombre de la lista que definimos en el bloque principal del programa es


listavalores:

listavalores=[10, 56, 23, 120, 94]

No hay ningún problema de definir dicha variable con el mismo nombre que el
parámetro de la función, es decir sería correcto nuestro programa si definíamos
en el bloque principal el siguiente código:

def sumarizar(lista):
suma=0
for x in range(len(lista)):
suma=suma+lista[x]
return suma

def mayor(lista):
may=lista[0]
for x in range(1,len(lista)):
if lista[x]>may:
may=lista[x]
return may

def menor(lista):
men=lista[0]
for x in range(1,len(lista)):
if lista[x]<men:
men=lista[x]
return men

# bloque principal del programa

lista=[10, 56, 23, 120, 94]


print("La lista completa es")
print(lista)
print("La suma de todos su elementos es", sumarizar(lista))
print("El mayor valor de la lista es", mayor(lista))
print("El menor valor de la lista es", menor(lista))

Debe quedar claro que la variable global definida en el bloque principal se


llama "lista" y los parámetros de las tres funciones también se llaman "lista".

Problema 2:
Crear y cargar por teclado en el bloque principal del programa una lista de 5
enteros. Implementar una función que imprima el mayor y el menor valor de la
lista.
Programa: ejercicio128.py
Ver video

def mayormenor(lista):
may=lista[0]
men=lista[0]
for x in range(1,len(lista)):
if lista[x]>may:
may=lista[x]
else:
if lista[x]<men:
men=lista[x]
print("El valor mayor de la lista es", may)
print("El valor menor de la lista es", men)

# bloque principal

lista=[]
for x in range(5):
valor=int(input("Ingrese valor:"))
lista.append(valor)
mayormenor(lista)
En el bloque principal de nuestro programa cargamos dentro de un for 5
valores enteros y los añadimos a la estructura de datos "lista".
Fuera del for procedemos a llamar a la función mayormenor y procedemos a
enviarle la lista para que pueda consultar sus datos.
Es importante notar que la función mayormenor no retorna nada sino ella es la
que tiene el objetivo de mostrar el mayor y menor valor de la lista.

Problemas propuestos
• Crear una lista de enteros por asignación. Definir una función que reciba
una lista de enteros y un segundo parámetro de tipo entero. Dentro de la
función mostrar cada elemento de la lista multiplicado por el valor entero
enviado.
• lista=[3, 7, 8, 10, 2]

• multiplicar(lista,3)

Ver video

• Desarrollar una función que reciba una lista de string y nos retorne el
que tiene más caracteres. Si hay más de uno con dicha cantidad de
caracteres debe retornar el que tiene un valor de componente más baja.
En el bloque principal iniciamos por asignación la lista de string:

• palabras=["enero", "febrero", "marzo", "abril", "mayo", "junio"]

• print("Palabra con mas caracteres:",mascaracteres(palabras))

Ver video

• Definir una lista de enteros por asignación en el bloque principal. Llamar


a una función que reciba la lista y nos retorne el producto de todos sus
elementos. Mostrar dicho producto en el bloque principal de nuestro
programa.

Ver video
Solución

Retornar

27 - Funciones: retorno de una lista


Hemos avanzado y visto que una función puede recibir como parámetros tipos
de datos simples como enteros, flotantes etc. y estructuras de datos tipo lista.
También hemos visto que la función mediante la palabra clave return puede
retornar un tipo de dato simple desde donde se la invocó.
Lo nuevo en este concepto es que una función también puede retornar una
estructura de datos tipo lista. Con esto estamos logrando que una función
retorne varios datos ya que una lista es una colección de datos.

Problema 1:
Confeccionar una función que cargue por teclado una lista de 5 enteros y la
retorne. Una segunda función debe recibir una lista y mostrar todos los valores
mayores a 10. Desde el bloque principal del programa llamar a ambas
funciones.
Programa: ejercicio132.py
Ver video

def carga_lista():
li=[]
for x in range(5):
valor=int(input("Ingrese valor:"))
li.append(valor)
return li

def imprimir_mayor10(li):
print("Elementos de la lista mayores a 10")
for x in range(len(li)):
if li[x]>10:
print(li[x])

# bloque principal del programa

lista=carga_lista()
imprimir_mayor10(lista)
Recordemos que el programa empieza a ejecutarse desde el bloque principal y
no se ejecutan cada función en forma lineal. Lo primero que hacemos en el
bloque principal del programa es llamar a la función carga_lista y se la
asignamos a una variable que recibirá la referencia de la función que se creará
en carga_lista:

lista=carga_lista()

La función carga_lista como vemos no tiene parámetros:

def carga_lista():

Dentro de la función definimos una variable local de tipo lista llamada li (el
nombre de la variable local puede ser cualquiera, inclusive se podría llamar
lista ya que no hay conflictos en definir variables con el mismo nombre en una
función y en el bloque principal):

li=[]

Seguidamente definimos un for que se repita 5 veces y solicitamos al operador


que ingrese enteros y los añadimos a la lista:

for x in range(5):
valor=int(input("Ingrese valor:"))
li.append(valor)
return li

Cuando finaliza el for ya tenemos almacenado en la lista los 5 enteros y


mediante la palabra clave de Python return procedemos a devolver a quien
invocó la función la variable "li".
Esto quiere decir que en el bloque principal del programa lista recibe la
referencia de "li":

lista=carga_lista()

Si no hacemos esa asignación la lista que devuelve la función carga_lista se


perdería:
carga_lista() # incorrecto al no asignarla a una variable el dato devuelto

La segunda línea de nuestro bloque principal es llamar a la función


imrprimir_mayor10 y pasar la lista que cargamos previamente:

imprimir_mayor10(lista)

La segunda función de nuestro programa es la imprimir_mayor10 que recibe


como parámetro una lista y procede a analizar cada elemento para ver si debe
imprimirse:

def imprimir_mayor10(li):
print("Elementos de la lista mayores a 10")
for x in range(len(li)):
if li[x]>10:
print(li[x])

Problema 2:
Confeccionar una función que cargue por teclado una lista de 5 enteros y la
retorne. Una segunda función debe recibir una lista y retornar el mayor y el
menor valor de la lista. Desde el bloque principal del programa llamar a ambas
funciones e imprimir el mayor y el menor de la lista.
Programa: ejercicio133.py
Ver video

def carga_lista():
li=[]
for x in range(5):
valor=int(input("Ingrese valor:"))
li.append(valor)
return li

def retornar_mayormenor(li):
ma=li[0]
me=li[0]
for x in range(1,len(li)):
if li[x]>ma:
ma=li[x]
else:
if li[x]<me:
me=li[x]
return [ma,me]

# bloque principal del programa

lista=carga_lista()
rango=retornar_mayormenor(lista)
print("Mayor elemento de la lista:",rango[0])
print("Menor elemento de la lista:",rango[1])
Lo interesante que tenemos que sacar de este ejemplo es que cuando
tenemos que retornar varios valores podemos utilizar una lista. La función
retornar_mayormenor debe devolver dos enteros, y la forma de hacerlo en
Python es mediante una lista.
En la función retornar_mayormenor definimos dos variables locales donde
almacenamos el primer elemento de la lista que recibimos como parámetro:

def retornar_mayormenor(li):
ma=li[0]
me=li[0]

Luego mediante un for procedemos a analizar el resto de los elementos de la


lista para verificar si hay alguno que sea mayor al que hemos considerado
mayor hasta ese momento, lo mismo con el menor:
for x in range(1,len(li)):
if li[x]>ma:
ma=li[x]
else:
if li[x]<me:
me=li[x]

Cuando sale del for ya tenemos almacenadas en las variables ma y me el valor


mayor y el valor menor de la lista.
La sintaxis para devolver ambos datos es crear una lista e indicando en cada
elementos la variable respectiva:

return [ma,me]

Ahora cuando llamo a esta función desde el bloque principal del programa
sabemos que nos retorna una lista y que el primer elemento representa el
mayor de la lista y el segundo elemento representa el menor de la lista:

rango=retornar_mayormenor(lista)
print("Mayor elemento de la lista:",rango[0])
print("Menor elemento de la lista:",rango[1])

Importante
Hemos visto que podemos retornar en una función una lista. Python también
nos permite descomponer los valores devueltos por la función en varias
variables que reciban cada elemento de esa lista:

# bloque principal del programa

lista=carga_lista()
mayor, menor=retornar_mayormenor(lista)
print("Mayor elemento de la lista:",mayor)
print("Menor elemento de la lista:",menor)

Como vemos definimos las variables mayor y menor y le asignamos el valor


que retorna la función mayormenor. Cada elemento de la lista se guarda en el
mismo orden, es decir la componente 0 de la lista se guarda en la variable
mayor y la componente 1 de la lista se guarda en la variable menor. Esto se
hace para que el programa sea mas legible en cuanto a nombre de variables y
el dato que almacenan.

Problema 3:
Desarrollar un programa que permita cargar 5 nombres de personas y sus
edades respectivas. Luego de realizar la carga por teclado de todos los datos
imprimir los nombres de las personas mayores de edad (mayores o iguales a
18 años)
Imprimir la edad promedio de las personas.
Programa: ejercicio134.py
Ver video

def cargar_datos():
nom=[]
ed=[]
for x in range(5):
v1=input("Ingrese el nombre de la persona
:")
nom.append(v1)
v2=int(input("Ingrese la edad:"))
ed.append(v2)
return [nom,ed]

def mayores_edad(nom,ed):
print("Nombres de personas mayores de edad")
for x in range(len(nom)):
if ed[x]>=18:
print(nom[x])
def promedio_edades(ed):
suma=0
for x in range(len(ed)):
suma=suma+ed[x]
promedio=suma//5
print("Edad promedio de las personas:",promed
io)

# bloque principal

nombres,edades=cargar_datos()
mayores_edad(nombres,edades)
promedio_edades(edades)
Para resolver este problema debemos crear y cargar dos listas paralelas. En
una guardamos los nombres de las personas y en la otra almacenamos las
edades.
Definimos una función cargar_datos que crea y carga las dos listas paralelos.
Las variables locales que almacenan dichas listas son nom y ed:

def cargar_datos():
nom=[]
ed=[]
for x in range(5):
v1=input("Ingrese el nombre de la persona:")
nom.append(v1)
v2=int(input("Ingrese la edad:"))
ed.append(v2)
return [nom,ed]

Esta función retorna una lista cuyos elementos son listas (es decir estamos en
presencia de listas con elementos tipo lista):

return [nom,ed]

Cuando llamamos a esta función desde el bloque principal de nuestro


programa le asignamos a dos variables:

nombres,edades=cargar_datos()

Ahora en las variables globales nombres y edades tenemos almacenados los


dos listas que cargamos en la función cargar_datos.
Como la función cargar_datos() retorna una lista de listas luego las dos
variables receptoras son listas.
En el bloque principal luego de llamar a cargar_datos que nos retorna las dos
listas procedemos a llamar a las otras funciones mayores_edad y
promedio_edades (nombres y edades son dos variables globales que
normalmente se inicializan con datos que devuelve una función y luego se las
enviamos a otras funciones para que las procesen):

# bloque principal

nombres,edades=cargar_datos()
mayores_edad(nombres,edades)
promedio_edades(edades)

El algoritmo de la función que imprime los nombres de las personas mayores


de edad es (recibe las dos listas):

def mayores_edad(nom,ed):
print("Nombres de personas mayores de edad")
for x in range(len(nom)):
if ed[x]>=18:
print(nom[x])

El algoritmo que calcula el promedio de edades es:

def promedio_edades(ed):
suma=0
for x in range(len(ed)):
suma=suma+ed[x]
promedio=suma//5
print("Edad promedio de las personas:",promedio)

Problemas propuestos
• En una empresa se almacenaron los sueldos de 10 personas.
Desarrollar las siguientes funciones y llamarlas desde el bloque principal:
1) Carga de los sueldos en una lista.
2) Impresión de todos los sueldos.
3) Cuántos tienen un sueldo superior a $4000.
4) Retornar el promedio de los sueldos.
5) Mostrar todos los sueldos que están por debajo del promedio.

Ver video

• Desarrollar una aplicación que permita ingresar por teclado los nombres
de 5 artículos y sus precios.
Definir las siguientes funciones:
1) Cargar los nombres de articulos y sus precios.
2) Imprimir los nombres y precios.
3) Imprimir el nombre de artículo con un precio mayor
4) Ingresar por teclado un importe y luego mostrar todos los artículos con
un precio menor igual al valor ingresado.
Ver video

• Confeccionar un programa que permita:


1) Cargar una lista de 10 elementos enteros.
2) Generar dos listas a partir de la primera. En una guardar los valores
positivos y en otra los negativos.
3) Imprimir las dos listas generadas.

Ver video
Solución

Retornar

28 - Funciones: con parámetros con


valor por defecto
En Python se pueden definir parámetros y asignarles un dato en la misma
cabecera de la función. Luego cuando llamamos a la función podemos o no
enviarle un valor al parámetro.
Los parámetros por defecto nos permiten crear funciones más flexibles y que
se pueden emplear en distintas circunstancias.

Problema 1:
Confeccionar una función que reciba un string como parámetro y en forma
opcional un segundo string con un caracter. La función debe mostrar el string
subrayado con el caracter que indica el segundo parámetro
Programa: ejercicio138.py
Ver video

def titulo_subrayado(titulo,caracter="*"):
print(titulo)
print(caracter*len(titulo))
# bloque principal

titulo_subrayado("Sistema de Administracion")
titulo_subrayado("Ventas","-")
Cuando ejecutamos esta aplicación podemos observar el siguiente resultado:

Lo primero importante en notar que la llamada a la función titulo_subrayado la


podemos hacer enviándole un dato o dos datos:

titulo_subrayado("Sistema de Administracion")
titulo_subrayado("Ventas","-")

Esto no podría ser correcto si no utilizamos una sintaxis especial cuando


declaramos los parámetros de la función:
def titulo_subrayado(titulo,caracter="*"):
print(titulo)
print(caracter*len(titulo))

Como vemos el parámetro caracter tiene una asignación de un valor por


defecto para los casos que llamamos a la función con un solo parámetro.
Cuando la llamamos a la función titulo_subrayado con un solo parámetro luego
el parámetro caracter almacena el valor "*". Si llamamos a la función y le
pasamos dos parámetros en nuestro ejemplo caracter almacena el string "-"
El algoritmo de la función es muy sencillo, imprimimos el primer parámetro:

print(titulo)

Para mostrar subrayado el titulo procedemos a imprimir el caracter del segundo


parámetro tantas veces como caracteres tenga el string del titulo. Utilizamos
una propiedad de los string en Python que nos permite utilizar el operador
matemático * y generar un string del largo del título:

print(caracter*len(titulo))

Importante
Los parámetros por defecto deben ser los últimos que se declaren en la
función. Se genera un error sintáctico si tratamos de definir una función
indicando primero el o los parámetros con valores por defecto:
Problema propuesto
• Confeccionar una función que reciba entre 2 y 5 enteros. La misma nos
debe retornar la suma de dichos valores. Debe tener tres parámetros por
defecto.

Ver video
Solución

Retornar

29 - Funciones: llamada a la función


con argumentos nombrados
Esta característica de Python nos permite llamar a la función indicando en
cualquier orden los parámetros de la misma, pero debemos especificar en la
llamada el nombre del parámetro y el valor a enviarle.

Problema 1:
Confeccionar una función que reciba el nombre de un operario, el pago por
hora y la cantidad de horas trabajadas. Debe mostrar su sueldo y el nombre.
Hacer la llamada de la función mediante argumentos nombrados.
Programa: ejercicio140.py
Ver video

def calcular_sueldo(nombre,costohora,cantidadhora
s):
sueldo=costohora*cantidadhoras
print(nombre,"trabajo",cantidadhoras,"y cobra
un sueldo de",sueldo)

# bloque principal

calcular_sueldo("juan",10,120)
calcular_sueldo(costohora=12,cantidadhoras=40,nom
bre="ana")
calcular_sueldo(cantidadhoras=90,nombre="luis",co
stohora=7)

Como podemos ver no hay ningún cambio cuando definimos la función:

def calcular_sueldo(nombre,costohora,cantidadhoras):
sueldo=costohora*cantidadhoras
print(nombre,"trabajo",cantidadhoras,"y cobra un sueldo de",sueldo)

Podemos llamarla como ya conocemos indicando los valores directamente:


calcular_sueldo("juan",10,120)

Pero también podemos indicar los datos en cualquier orden pero con la
obligación de anteceder el nombre del parámetro:

calcular_sueldo(costohora=12,cantidadhoras=40,nombre="ana")
calcular_sueldo(cantidadhoras=90,nombre="luis",costohora=7)

Importante
Ahora vamos a profundizar la función print que hemos utilizado desde los
primeros conceptos.
Como hemos trabajado hasta ahora cada vez que se llama a la función print se
muestran todos los datos que le enviamos separados por coma y provoca un
salto de línea al final.
Por ejemplo si ejecutamos

print("uno")
print("dos")

En pantalla aparece:

uno
dos

La función print tiene un parámetro llamado end, también hay que tener en
cuenta que este parámetro por defecto tiene asignado "\n" que es el salto de
línea y es por eso que cada vez que se ejecuta un print se produce un salto de
línea.
Podemos indicar al parámetro end otro valor, por ejemplo un guión:

print("uno",end="-")
print("dos")

Ahora el resultado de ejecutar este programa es:

uno-dos

Ahora vemos que al llamar a print pidiendo que imprima "uno" e indicando que
en lugar de producir un salto de línea muestre un guión:

print("uno",end="-")
Problema 2:
Cargar una lista de 10 enteros, luego mostrarlos por pantalla a cada elemento
separados por una coma.
Programa: ejercicio141.py
Ver video

def cargar():
lista=[]
for x in range(10):
valor=int(input("Ingrese valor:"))
lista.append(valor)
return lista

def imprimir(lista):
for x in range(len(lista)):
print(lista[x], end=",")

# bloque principal

lista=cargar()
imprimir(lista)
Lo nuevo en este problema aparece cuando imprimimos los elementos de la
lista, como necesitamos que se muestren todos en la misma línea y separados
por coma cargamos en el parámetro end la cadena ",":

def imprimir(lista):
for x in range(len(lista)):
print(lista[x], end=",")

Si no indicamos el parámetro end luego aparecen todos los datos en líneas


distintas en pantalla.
Otro argumento nombrado importante para la función print de Python se llama
"sep", este indica que debe mostrarse entre cada dato a mostrar en la misma
llamada print.
Por ejemplo si ejecutamos:

print("uno","dos","tres")

Luego el resultado es la impresión de los string en la misma línea y separados


por un caracter en blanco (esto debido a que el parámetro sep tiene un valor
por defecto de un espacio en blanco (sep=" "):

uno dos tres

Entonces podemos asignar al parámetro sep el valor que necesitemos, por


ejemplo una coma:

print("uno","dos","tres",sep=",")

Luego el resultado en pantalla será:

uno,dos,tres

Problema propuesto
• Elaborar una función que muestre la tabla de multiplicar del valor que le
enviemos como parámetro. Definir un segundo parámetro llamado
termino que por defecto almacene el valor 10. Se deben mostrar tantos
términos de la tabla de multiplicar como lo indica el segundo parámetro.
Llamar a la función desde el bloque principal de nuestro programa con
argumentos nombrados.

Ver video
Solución

Retornar
30 - Funciones: con cantidad variable
de parámetros
Otra variante en la declaración de una función en Python es la definición de
una cantidad variable de parámetros.
Para definir una cantidad variable de parámetros debemos anteceder el
caracter asterísco (*) al último parámetro de la función.

Problema 1:
Confeccionar una función que reciba entre 2 y n (siendo n = 2,3,4,5,6 etc.)
valores enteros, retornar la suma de dichos parámetros.
Programa: ejercicio143.py
Ver video

def sumar(v1,v2,*lista):
suma=v1+v2
for x in range(len(lista)):
suma=suma+lista[x]
return suma

# bloque principal

print("La suma de 1+2")


print(sumar(1,2))
print("La suma de 1+2+3+4")
print(sumar(1,2,3,4))
print("La suma de 1+2+3+4+5+6+7+8+9+10")
print(sumar(1,2,3,4,5,6,7,8,9,10))
Para este problema definimos tres parámetros en la función,el primeros y el
segundo reciben enteros y el tercero recibe una tupla (por ahora pensemos
que una tupla es lo mismo que una lista, más adelante veremos sus
diferencias):

def sumar(v1,v2,*lista):
suma=v1+v2
for x in range(len(lista)):
suma=suma+lista[x]
return suma

Sumamos los dos primeros valores y luego recorremos la lista y también


sumamos sus elementos.
Cuando llamamos a la función sumar podemos hacerlo enviando solo dos
parámetros (la lista está vacía en este caso):

print(sumar(1,2))

Podemos llamar la función enviando 4 parámetros, en este caso la lista tiene


dos elementos:

print(sumar(1,2,3,4))

Y en general podemos llamar la función enviando cualquier cantidad de


enteros:

print(sumar(1,2,3,4,5,6,7,8,9,10))

Desempaquetar una lista o tupla


Puede ser que tengamos una función que recibe una cantidad fija de
parámetros y necesitemos llamarla enviando valores que se encuentran en una
lista o tupla. La forma más sencilla es anteceder el caracter * al nombre de la
variable:
Ver video

def sumar(v1, v2, v3):


return v1 + v2 + v3

li=[2, 4, 5]
su=sumar(*li)
print(su)
La función 'sumar' tiene 3 parámetro y la llamamos con la sintaxis:

su=sumar(*li)

Con el caracter asterisco estamos haciendo que se descomponga la lista en


sus tres elementos:

su=sumar(li[0], li[1], li[2])

Problema propuesto
• Confeccionar una función que reciba una serie de edades y me retorne
la cantidad que son mayores o iguales a 18 (como mínimo se envía un
entero a la función)

Ver video
Solución

Retornar

31 - Estructura de datos tipo Tupla


Hemos desarrollado gran cantidad de algoritmos empleando tipos de datos
simples como enteros, flotantes, cadenas de caracteres y estructuras de datos
tipo lista.
Vamos a ver otra estructura de datos llamada Tupla.
Una tupla permite almacenar una colección de datos no necesariamente del
mismo tipo. Los datos de la tupla son inmutables a diferencia de las listas que
son mutables.
Una vez inicializada la tupla no podemos agregar, borrar o modificar sus
elementos.
La sintaxis para definir una tupla es indicar entre paréntesis sus valores:
Problema 1:
Definir varias tuplas e imprimir sus elementos.
Programa: ejercicio146.py
Ver video

tupla=(1, 2, 3)
fecha=(25, "Diciembre", 2016)
punto=(10, 2)
persona=("Rodriguez", "Pablo", 43)
print(tupla)
print(fecha)
print(punto)
print(persona)
Como vemos el lenguaje Python diferencia una tupla de una lista en el
momento que la definimos:

tupla=(1, 2, 3)
fecha=(25, "Diciembre", 2016)
punto=(10, 2)
persona=("Rodriguez", "Pablo", 43)

Utilizamos paréntesis para agrupar los distintos elementos de la tupla.


Podemos acceder a los elementos de una tupla en forma similar a una lista por
medio de un subíndice:

print(punto[0]) # primer elemento de la tupla


print(punto[1]) # segundo elemento de la tupla

Es muy IMPORTANTE tener en cuenta que los elementos de la tupla son


inmutables, es incorrecto tratar de hacer esta asignación a un elemento de la
tupla:

punto[0]=70

Nos genera el siguiente error:

Traceback (most recent call last):


File "C:/programaspython/ejercicio146.py", line 11, in
punto[0]=70
TypeError: 'tuple' object does not support item assignment

Utilizamos una tupla para agrupar datos que por su naturaleza están
relacionados y que no serán modificados durante la ejecución del programa.

Problema 2:
Desarrollar una función que solicite la carga del dia, mes y año y almacene
dichos datos en una tupla que luego debe retornar. La segunda función a
implementar debe recibir una tupla con la fecha y mostrarla por pantalla.
Programa: ejercicio147.py
Ver video

def cargar_fecha():
dd=int(input("Ingrese numero de dia:"))
mm=int(input("Ingrese numero de mes:"))
aa=int(input("Ingrese numero de año:"))
return (dd,mm,aa)

def imprimir_fecha(fecha):
print(fecha[0],fecha[1],fecha[2],sep="/")

# bloque principal

fecha=cargar_fecha()
imprimir_fecha(fecha)
En la función cargar_fecha cargamos tres enteros por teclado y procedemos a
crear una tupla indicando entre paréntesis los nombres de las tres variables y
procedemos a retornarla:

def cargar_fecha():
dd=int(input("Ingrese numero de dia:"))
mm=int(input("Ingrese numero de mes:"))
aa=int(input("Ingrese numero de año:"))
return (dd,mm,aa)

En el bloque principal llamamos a la función cargar_fecha y el valor devuelto se


almacena en la variable fecha (recordemos que la función devuelve una tupla):

fecha=cargar_fecha()
Definimos una función que recibe la tupla y procede a mostrar el contenido
separado por el caracter "/":

def imprimir_fecha(fecha):
print(fecha[0],fecha[1],fecha[2],sep="/")

Conversión de tuplas a listas y viceversa.


Otra herramienta que nos proporciona Python es la conversión de tuplas a
listas y viceversa mediante las funciones:

list(parametro de tipo tupla)


tuple(parametro de tipo lista)

Problema 3:
Definir una tupla con tres valores enteros. Convertir el contenido de la tupla a
tipo lista. Modificar la lista y luego convertir la lista en tupla.
Programa: ejercicio148.py
Ver video

fechatupla1=(25, 12, 2016)


print("Imprimimos la primer tupla")
print(fechatupla1)
fechalista=list(fechatupla1)
print("Imprimimos la lista que se le copio la tup
la anterior")
print(fechalista)
fechalista[0]=31
print("Imprimimos la lista ya modificada")
print(fechalista)
fechatupla2=tuple(fechalista)
print("Imprimimos la segunda tupla que se le copi
o la lista")
print(fechatupla2)

Empaquetado y desempaquetado de tuplas.


Podemos generar una tupla asignando a una variable un conjunto de variables
o valores separados por coma:

x=10
y=30
punto=x,y
print(punto)

tenemos dos variables enteras x e y. Luego se genera una tupla llamada punto
con dos elementos.

fecha=(25, "diciembre", 2016)


print(fecha)
dd,mm,aa=fecha
print("Dia",dd)
print("Mes",mm)
print("Año",aa)

El desempaquetado de la tupla "fecha" se produce cuando definimos tres


variables separadas por coma y le asignamos una tupla:

dd,mm,aa=fecha

Es importante tener en cuenta de definir el mismo número de variables que la


cantidad de elementos de la tupla.

Problemas propuestos
• Confeccionar un programa con las siguientes funciones:
1)Cargar una lista de 5 enteros.
2)Retornar el mayor y menor valor de la lista mediante una tupla.
Desempaquetar la tupla en el bloque principal y mostrar el mayor y
menor.

Ver video

• Confeccionar un programa con las siguientes funciones:


1)Cargar el nombre de un empleado y su sueldo. Retornar una tupla con
dichos valores
2)Una función que reciba como parámetro dos tuplas con los nombres y
sueldos de empleados y muestre el nombre del empleado con sueldo
mayor.
En el bloque principal del programa llamar dos veces a la función de
carga y seguidamente llamar a la función que muestra el nombre de
empleado con sueldo mayor.

• # bloque principal

• empleado1=cargar_empleado()

• empleado2=cargar_empleado()

• mayor_sueldo(empleado1,empleado2)

Ver video
Solución

Retornar

32 - Listas y tuplas anidadas


Hemos visto dos estructuras de datos fundamentales en Python que son las
listas y las tuplas.
La lista es una estructura mutable (es decir podemos modificar sus elementos,
agregar y borrar) en cambio una tupla es una secuencia de datos inmutable, es
decir una vez definida no puede cambiar.
En Python vimos que podemos definir elementos de una lista que sean de tipo
lista, en ese caso decimos que tenemos una lista anidada.
Ahora que vimos tuplas también podemos crear tuplas anidadas.
En general podemos crear y combinar tuplas con elementos de tipo lista y
viceversa, es decir listas con componente tipo tupla.
Programa: ejercicio151.py
Ver video

empleado=["juan", 53, (25, 11, 1999)]


print(empleado)
empleado.append((1, 1, 2016))
print(empleado)
alumno=("pedro",[7, 9])
print(alumno)
alumno[1].append(10)
print(alumno)
Por ejemplo definimos la lista llamada empleado con tres elementos: en el
primero almacenamos su nombre, en el segundo su edad y en el tercero la
fecha de ingreso a trabajar en la empresa (esta se trata de una tupla) Podemos
más adelante durante la ejecución del programa agregar otro elemento a la
lista con por ejemplo la fecha que se fue de la empresa:

empleado=["juan", 53, (25, 11, 1999)]


print(empleado)
empleado.append((1, 1, 2016))
print(empleado)

Tenemos definida la tupla llamada alumno con dos elementos, en el primero


almacenamos su nombre y en el segundo una lista con las notas que ha
obtenido hasta ahora:

alumno=("pedro",[7, 9])
print(alumno)

Podemos durante la ejecución del programa agregar una nueva nota a dicho
alumno:

alumno[1].append(10)
print(alumno)
Problema 1:
Almacenar en una lista de 5 elementos tuplas que guarden el nombre de un
pais y la cantidad de habitantes.
Definir tres funciones, en la primera cargar la lista, en la segunda imprimirla y
en la tercera mostrar el nombre del país con mayor cantidad de habitantes.
Programa: ejercicio152.py
Ver video

def cargar_paisespoblacion():
paises=[]
for x in range(5):
nom=input("Ingresar el nombre del pais:")
cant=int(input("Ingrese la cantidad de ha
bitantes:"))
paises.append((nom,cant))
return paises

def imprimir(paises):
print("Paises y su poblacion")
for x in range(len(paises)):
print(paises[x][0],paises[x][1])

def pais_maspoblacion(paises):
pos=0
for x in range(1,len(paises)):
if paises[x][1]>paises[pos][1]:
pos=x
print("Pais con mayor cantidad de habitantes:
",paises[pos][0])

# bloque principal

paises=cargar_paisespoblacion()
imprimir(paises)
pais_maspoblacion(paises)
En la primer función definimos una lista llamada paises y dentro de una
estructura repetitiva cargamos un string con el nombre del pais y una variable
entera con la cantidad de habitantes, luego agregamos un elemento a la lista
de tipo tupla:
def cargar_paisespoblacion():
paises=[]
for x in range(5):
nom=input("Ingresar el nombre del pais:")
cant=int(input("Ingrese la cantidad de habitantes:"))
paises.append((nom,cant))
return paises

La segunda función recibe la lista y procedemos a mostrar cada tupla


contenida en cada elemento de la lista:

def imprimir(paises):
print("Paises y su poblacion")
for x in range(len(paises)):
print(paises[x][0],paises[x][1])

Para identificar el nombre del pais con mayor población iniciamos una variable
pos con el valor 0 indicando que en dicha posición de la lista se encuentra el
pais con mayor poblacion, luego dentro del for controlamos las demás tuplas
almacenadas en la lista si hay un pais con mayor población:

def pais_maspoblacion(paises):
pos=0
for x in range(1,len(paises)):
if paises[x][1]>paises[pos][1]:
pos=x
print("Pais con mayor cantidad de habitantes:",paises[pos][0])

Problemas propuestos
• Almacenar en una lista 5 empleados, cada elemento de la lista es una
sub lista con el nombre del empleado junto a sus últimos tres sueldos
(estos tres valores en una tupla)
El programa debe tener las siguientes funciones:
1)Carga de los nombres de empleados y sus últimos tres sueldos.
2)Imprimir el monto total cobrado por cada empleado.
3)Imprimir los nombres de empleados que tuvieron un ingreso trimestral
mayor a 10000 en los últimos tres meses.
Tener en cuenta que la estructura de datos si se carga por asignación
debería ser similar a:

• empleados = [["juan",(2000,3000,4233)] , ["ana",(3444,1000,5333)] , etc.


]

Ver video

• Se tiene que cargar los votos obtenidos por tres candidatos a una
elección.
En una lista cargar en la primer componente el nombre del candidato y
en la segunda componente cargar una lista con componentes de tipo
tupla con el nombre de la provincia y la cantidad de votos obtenidos en
dicha provincia.

Se deben cargar los datos por teclado, pero si se cargaran por


asignación tendría una estructura similar a esta:

candidatos=[ ("juan",[("cordoba",100),("buenos aires",200)]) , ("ana", [(


"cordoba",55)]) , ("luis", [("buenos aires",20)]) ]

1) Función para cargar todos los candidatos, sus nombres y las


provincias con los votos obtenidos.
2) Imprimir el nombre del candidato y la cantidad total de votos obtenidos
en todas las provincias.
Ver video
Solución

Retornar

33 - Variantes de la estructura
repetitiva for para recorrer tuplas y
listas
Hasta ahora siempre que recorremos una lista o una tupla utilizando un for
procedemos de la siguiente manera:
lista=[2, 3, 50, 7, 9]

for x in range(len(lista)):
print(lista[x])

Esta forma de recorrer la lista es utilizada obligatoriamente cuando queremos


modificar sus elementos como podría ser:

lista=[2, 3, 50, 7, 9]

print(lista) # [2, 3, 50, 7, 9]

for x in range(len(lista)):
if lista[x]<10:
lista[x]=0

print(lista) # [0, 0, 50, 0, 0]

Ahora veremos una segunda forma de acceder a los elementos de una lista
con la estructura repetitiva for sin indicar subíndices.

lista=[2, 3, 50, 7, 9]

for elemento in lista:


print(elemento)

Como podemos ver la instrucción for requiere una variable (en este ejemplo
llamada elemento), luego la palabra clave in y por último el nombre de la lista.
El bloque del for se ejecuta tantas veces como elementos tenga la lista, y en
cada vuelta del for la variable elemento almacena un valor de la lista.

Problema 1:
Confeccionar un programa que permita la carga de una lista de 5 enteros por
teclado.
Luego en otras funciones:
1) Imprimirla en forma completa.
2) Obtener y mostrar el mayor.
3) Mostrar la suma de todas sus componentes.
Utilizar la nueva sintaxis de for vista en este concepto.
Programa: ejercicio155.py
Ver video

def cargar():
lista=[]
for x in range(5):
num=int(input("Ingrese un valor:"))
lista.append(num)
return lista

def imprimir(lista):
print("Lista completa")
for elemento in lista:
print(elemento)

def mayor(lista):
may=lista[0]
for elemento in lista:
if elemento>may:
may=elemento
print("El elemento mayor de la lista es",may)

def sumar_elementos(lista):
suma=0
for elemento in lista:
suma=suma+elemento
print("La suma de todos sus elementos es",sum
a)

# bloque principal

lista=cargar()
imprimir(lista)
mayor(lista)
sumar_elementos(lista)
En la carga planteamos un for que se repita cinco veces y es imposible recorrer
la lista con el for ya que antes de entrar al for la lista se define vacía:

def cargar():
lista=[]
for x in range(5):
num=int(input("Ingrese un valor:"))
lista.append(num)
return lista

Las funciones imprimir, mayor y sumar_elementos son lugares muy


convenientes para acceder a los elementos de la lista con la nueva sintaxis del
for:

def imprimir(lista):
print("Lista completa")
for elemento in lista:
print(elemento)

def mayor(lista):
may=lista[0]
for elemento in lista:
if elemento>may:
may=elemento
print("El elemento mayor de la lista es",may)

def sumar_elementos(lista):
suma=0
for elemento in lista:
suma=suma+elemento
print("La suma de todos sus elementos es",suma)

Problema 2:
Almacenar en una lista de 5 elementos las tuplas con el nombre de empleado y
su sueldo.
Implementar las funciones:
1) Carga de empleados.
2) Impresión de los empleados y sus sueldos.
3) Nombre del empleado con sueldo mayor.
4) Cantidad de empleados con sueldo menor a 1000.
Programa: ejercicio156.py
Ver video

def cargar():
empleados=[]
for x in range(5):
nombre=input("Nombre del empleado:")
sueldo=int(input("Ingrese el sueldo:"))
empleados.append((nombre,sueldo))
return empleados
def imprimir(empleados):
print("Listado de los nombres de empleados y
sus sueldos")
for nombre,sueldo in empleados:
print(nombre,sueldo)

def mayor_sueldo(empleados):
empleado=empleados[0]
for emp in empleados:
if emp[1]>empleado[1]:
empleado=emp
print("Empleado con mayor sueldo:",empleado[0
],"su sueldo es",empleado[1])

def sueldos_menor1000(empleados):
cant=0
for empleado in empleados:
if empleado[1]<1000:
cant=cant+1
print("Cantidad de empleados con un sueldo me
nor a 1000 son:",cant)

# bloque principal
empleados=cargar()
imprimir(empleados)
mayor_sueldo(empleados)
sueldos_menor1000(empleados)
La carga de la lista con elementos de tipo tupla ya la conocemos de conceptos
anteriores:

def cargar():
empleados=[]
for x in range(5):
nombre=input("Nombre del empleado:")
sueldo=int(input("Ingrese el sueldo:"))
empleados.append((nombre,sueldo))
return empleados

Algo nuevo podemos ver ahora en el for para recuperar cada tupla almacenada
en la lista. Podemos ver que desempaquetamos la tupla que devuelve el for en
cada vuelta en las variables nombre y sueldo. Esto nos facilita la impresión de
los datos sin tener que indicar subíndices para los elementos de la tupla:

def imprimir(empleados):
print("Listado de los nombres de empleados y sus sueldos")
for nombre,sueldo in empleados:
print(nombre,sueldo)

Para obtener el sueldo mayor y el nombre del empleado definimos una variable
local llamada empleado que almacene el primer elemento de la lista
empleados.
En cada vuelta del for en la variable emp se almacena una tupla de la lista
empleados y procedemos a analizar si el sueldo es mayor al que hemos
considerado mayor hasta ese momento, en caso afirmativo actualizamos la
variable empleado:

def mayor_sueldo(empleados):
empleado=empleados[0]
for emp in empleados:
if emp[1]>empleado[1]:
empleado=emp
print("Empleado con mayor sueldo:",empleado[0],"su sueldo es",empleado[1])

En forma similar procesamos la lista para contar la cantidad de empleados con


un sueldo menor a 1000:

def sueldos_menor1000(empleados):
cant=0
for empleado in empleados:
if empleado[1]<1000:
cant=cant+1
print("Cantidad de empleados con un sueldo menor a 1000 son:",cant)

Desde el bloque principal procedemos a llamar a las distintas funciones:

# bloque principal

empleados=cargar()
imprimir(empleados)
mayor_sueldo(empleados)
sueldos_menor1000(empleados)

Problemas propuestos
• Definir una función que cargue una lista con palabras y la retorne.
Luego otra función tiene que mostrar todas las palabras de la lista que
tienen más de 5 caracteres.

Ver video

• Almacenar los nombres de 5 productos y sus precios. Utilizar una lista y


cada elemento una tupla con el nombre y el precio.
Desarrollar las funciones:
1) Cargar por teclado.
2) Listar los productos y precios.
3) Imprimir los productos con precios comprendidos entre 10 y 15.

Ver video
Solución
Retornar

34 - Estructura de datos tipo


diccionario
Hasta ahora hemos presentado dos estructuras fundamentales de datos en
Python: listas y tuplas. Ahora presentaremos y comenzaremos a utilizar la
estructura de datos tipo diccionario.
La estructura de datos tipo diccionario utiliza una clave para acceder a un
valor. El subíndice puede ser un entero, un float, un string, una tupla etc. (en
general cualquier tipo de dato inmutable)
Podemos relacionarlo con conceptos que conocemos:

• Un diccionario tradicional que conocemos podemos utilizar un


diccionario de Python para representarlo. La clave sería la palabra y el
valor sería la definición de dicha palabra.

• Una agenda personal también la podemos representar como un


diccionario. La fecha sería la clave y las actividades de dicha fecha sería
el valor.

• Un conjunto de usuarios de un sitio web podemos almacenarlo en un


diccionario. El nombre de usuario sería la clave y como valor podríamos
almacenar su mail, clave, fechas de login etc.

Hay muchos problemas de la realidad que se pueden representar mediante un


diccionario de Python.
Recordemos que las listas son mutables y las tuplas inmutables. Un diccionario
es una estructura de datos mutable es decir podemos agregar elementos,
modificar y borrar.
Definición de un diccionario por asignación.

productos={"manzanas":39, "peras":32, "lechuga":17}


print(productos)

Como vemos debemos encerrar entre llaves los elementos separados por
coma. A cada elementos debemos indicar del lado izquierdo del caracter : la
clave y al lado derecho el valor asignado para dicha clave. Por ejemplo para la
clave "peras" tenemos asociado el valor entero 32.

Problema 1:
En el bloque principal del programa definir un diccionario que almacene los
nombres de paises como clave y como valor la cantidad de habitantes.
Implementar una función para mostrar cada clave y valor.
Programa: ejercicio159.py
Ver video

def imprimir(paises):
for clave in paises:
print(clave, paises[clave])

# bloque principal
paises={"argentina":40000000, "españa":46000000,
"brasil":190000000, "uruguay": 3400000}
imprimir(paises)
En el bloque principal de nuestro programa inicializamos un diccionario con
cuatro elementos y lo pasamos a la función imprimir:

paises={"argentina":40000000, "españa":46000000, "brasil":190000000, "uruguay":


3400000}
imprimir(paises)

Mediante el ciclo repetitivo for podemos acceder sucesivamente a las claves


almacenadas en el diccionario y luego conociendo la clave podemos acceder al
valor de forma similar a las listas indicando como subíndice la clave:

def imprimir(paises):
for clave in paises:
print(clave, paises[clave])

Problema 2:
Crear un diccionario que permita almacenar 5 artículos, utilizar como clave el
nombre de productos y como valor el precio del mismo.
Desarrollar además las funciones de:
1) Imprimir en forma completa el diccionario
2) Imprimir solo los artículos con precio superior a 100.
Programa: ejercicio160.py
Ver video

def cargar():
productos={}
for x in range(5):
nombre=input("Ingrese el nombre del produ
cto:")
precio=int(input("Ingrese el precio:"))
productos[nombre]=precio
return productos

def imprimir(productos):
print("Listado de todos los articulos")
for nombre in productos:
print(nombre, productos[nombre])

def imprimir_mayor100(productos):
print("Listado de articulos con precios mayor
es a 100")
for nombre in productos:
if productos[nombre]>100:
print(nombre)

# bloque principal

productos=cargar()
imprimir(productos)
imprimir_mayor100(productos)
Para agregar elementos a un diccionario procedemos a asignar el valor e
indicamos como subíndice la clave:

nombre=input("Ingrese el nombre del producto:")


precio=int(input("Ingrese el precio:"))
productos[nombre]=precio
Si ya existe el nombre de producto en el diccionario se modifica el valor para
esa clave.
Operador in con diccionarios
Para consultar si una clave se encuentra en el diccionario podemos utilizar el
operador in:

if clave in diccionario:
print(diccionario[clave])

Esto muy conveniente hacerlo ya que si no existe la clave produce un error al


tratar de accederlo:

print(diccionario[clave])

Problema 3:
Desarrollar una aplicación que nos permita crear un diccionario
ingles/castellano. La clave es la palabra en ingles y el valor es la palabra en
castellano.
Crear las siguientes funciones:
1) Cargar el diccionario.
2) Listado completo del diccionario.
3) Ingresar por teclado una palabra en ingles y si existe en el diccionario
mostrar su traducción.
Programa: ejercicio161.py
Ver video

def cargar():
diccionario={}
continua="s"
while continua=="s":
caste=input("Ingrese palabra en castellan
o:")
ing=input("Ingrese palabra en ingles:")
diccionario[ing]=caste
continua=input("Quiere cargar otra palabr
a:[s/n]")
return diccionario

def imprimir(diccionario):
print("Listado completo del diccionario")
for ingles in diccionario:
print(ingles,diccionario[ingles])

def consulta_palabra(diccionario):
pal=input("Ingrese la palabra en ingles a con
sultar:")
if pal in diccionario:
print("En castellano significa:",dicciona
rio[pal])

# bloque principal

diccionario=cargar()
imprimir(diccionario)
consulta_palabra(diccionario)
La función de cargar crea el diccionario y va solicitando la palabra en
castellano y su traducción. Luego de agregar un elementos se solicita el
ingrese de una variable string pidiendo que confirme si quiere cargar otra
palabra en el diccionario o finalizar:
def cargar():
diccionario={}
continua="s"
while continua=="s":
caste=input("Ingrese palabra en castellano:")
ing=input("Ingrese palabra en ingles:")
diccionario[ing]=caste
continua=input("Quiere cargar otra palabra:[s/n]")
return diccionario

La función imprimir muestra el diccionario en forma completa:

def imprimir(diccionario):
print("Listado completo del diccionario")
for ingles in diccionario:
print(ingles,diccionario[ingles])

Lo nuevo aparece cuando queremos consultar la traducción de una palabra.


Se solicita al operador que ingrese la palabra en ingles que desconoce y
mediante el operador in verificamos si dicha palabra se encuentra dentro del
diccionario, en caso afirmativo procedemos a mostrar el valor del diccionario,
es decir la palabra en castellano:

def consulta_palabra(diccionario):
pal=input("Ingrese la palabra en ingles a consultar:")
if pal in diccionario:
print("En castellano significa:",diccionario[pal])

Problema propuesto
• Crear un diccionario en Python que defina como clave el número de
documento de una persona y como valor un string con su nombre.
Desarrollar las siguientes funciones:
1) Cargar por teclado los datos de 4 personas.
2) Listado completo del diccionario.
3) Consulta del nombre de una persona ingresando su número de
documento.

Ver video
Solución

Retornar

35 - Diccionarios: con valores de tipo


listas, tuplas y diccionarios
Lo más poderoso que podemos encontrar en las estructuras de datos en
Python es que podemos definir elementos que sean también estructuras de
datos. En general se dice que podemos anidar una estructura de datos dentro
de otra estructura de datos.
Ya vimos en conceptos anteriores que podemos definir elementos de una lista
que sean también de tipo lista o de tipo tupla.
Hemos dicho que un diccionario consta de claves y valores para esas claves.
Desarrollaremos problemas donde los valores para esas claves sean tuplas y o
listas.

Problema 1:
Confeccionar un programa que permita cargar un código de producto como
clave en un diccionario. Guardar para dicha clave el nombre del producto, su
precio y cantidad en stock.
Implementar las siguientes actividades:
1) Carga de datos en el diccionario.
2) Listado completo de productos.
3) Consulta de un producto por su clave, mostrar el nombre, precio y stock.
4) Listado de todos los productos que tengan un stock con valor cero.
Programa: ejercicio163.py
Ver video

def cargar():
productos={}
continua="s"
while continua=="s":
codigo=int(input("Ingrese el codigo del p
roducto:"))
descripcion=input("Ingrese la descripcion
:")
precio=float(input("Ingrese el precio:"))
stock=int(input("Ingrese el stock actual:
"))
productos[codigo]=(descripcion,precio,sto
ck)
continua=input("Desea cargar otro product
o[s/n]?")
return productos

def imprimir(productos):
print("Listado completo de productos:")
for codigo in productos:
print(codigo,productos[codigo][0],product
os[codigo][1],productos[codigo][2])

def consulta(productos):
codigo=int(input("Ingrese el codigo de articu
lo a consultar:"))
if codigo in productos:
print(productos[codigo][0],productos[codi
go][1],productos[codigo][2])
def listado_stock_cero(productos):
print("Listado de articulos con stock en cero
:")
for codigo in productos:
if productos[codigo][2]==0:
print(codigo,productos[codigo][0],pro
ductos[codigo][1],productos[codigo][2])

# bloque principal

productos=cargar()
imprimir(productos)
consulta(productos)
listado_stock_cero(productos)

La función de cargar crea un diccionario llamado "productos" y mediante una


estructura repetitiva añadimos en cada vuelta en el diccionario una entrada. La
clave del diccionario es el código del producto y el valor del diccionario es una
tupla que almacena la descripción del producto, su precio y su stock:

def cargar():
productos={}
continua="s"
while continua=="s":
codigo=int(input("Ingrese el codigo del producto:"))
descripcion=input("Ingrese la descripcion:")
precio=float(input("Ingrese el precio:"))
stock=int(input("Ingrese el stock actual:"))
productos[codigo]=(descripcion,precio,stock)
continua=input("Desea cargar otro producto[s/n]?")
return productos

En la función de imprimir recorremos el diccionario mediante un for in y


recuperamos en cada paso una clave y mediante esta accedemos al valor que
como sabemos se trata de una tupla que contiene 3 elementos:

def imprimir(productos):
print("Listado completo de productos:")
for codigo in productos:
print(codigo,productos[codigo][0],productos[codigo][1],productos[codigo]
[2])

Para la consulta por el codigo del artículo ingresamos un entero por teclado y
luego verificamos si dicho número está como clave dentro del diccionario
productos, en el caso afirmativo mostramos los valores de la tupla:

def consulta(productos):
codigo=int(input("Ingrese el codigo de articulo a consultar:"))
if codigo in productos:
print(productos[codigo][0],productos[codigo][1],productos[codigo][2])

Finalmente la función para listar todos los artículos con stock en cero
procedemos a analizar el stock de cada producto dentro de un for, en el caso
que la tercer componente de la tupla almacena un cero significa que no hay
productos en stock:

def listado_stock_cero(productos):
print("Listado de articulos con stock en cero:")
for codigo in productos:
if productos[codigo][2]==0:
print(codigo,productos[codigo][0],productos[codigo][1],productos[cod
igo][2])

Problema 2:
Confeccionar una agenda. Utilizar un diccionario cuya clave sea la fecha.
Permitir almacenar distintas actividades para la misma fecha (se ingresa la
hora y la actividad)
Implementar las siguientes funciones:
1) Carga de datos en la agenda.
2) Listado completo de la agenda.
3) Consulta de una fecha.
Programa: ejercicio164.py
Ver video

def cargar():
agenda={}
continua1="s"
while continua1=="s":
fecha=input("ingrese la fecha con formato
dd/mm/aa:")
continua2="s"
lista=[]
while continua2=="s":
hora=input("Ingrese la hora de la act
ividad con formato hh:mm ")
actividad=input("Ingrese la descripco
n de la actividad:")
lista.append((hora,actividad))
continua2=input("Ingresa otra activid
ad para la misma fecha[s/n]:")
agenda[fecha]=lista
continua1=input("Ingresa otra fecha[s/n]:
")
return agenda

def imprimir(agenda):
print("Listado completa de la agenda")
for fecha in agenda:
print("Para la fecha:",fecha)
for hora,actividad in agenda[fecha]:
print(hora,actividad)

def consulta_fecha(agenda):
fecha=input("Ingrese la fecha que desea consu
ltar:")
if fecha in agenda:
for hora,actividad in agenda[fecha]:
print(hora,actividad)
else:
print("No hay actividades agendadas para
dicha fecha")

# bloque principal

agenda=cargar()
imprimir(agenda)
consulta_fecha(agenda)
Un ejemplo de ejecutar este programa tenemos la siguiente pantalla:
La carga de la agenda se compone de dos estructuras repetitivas anidadas.
Previo a comenzar la primer estructura repetitiva creamos el diccionario
llamado agenda:

def cargar():
agenda={}

El primer ciclo se repite mientras haya más fechas que cargar. Solicitamos que
ingrese una fecha, creamos una lista para guardar todas las horas y
actividades que hay par dicha fecha:

continua1="s"
while continua1=="s":
fecha=input("ingrese la fecha con formato dd/mm/aa:")
continua2="s"
lista=[]

El segundo ciclo se repite mientras haya más actividades para el mismo día:

while continua2=="s":
hora=input("Ingrese la hora de la actividad con formato hh:mm ")
actividad=input("Ingrese la descripcon de la actividad:")
lista.append((hora,actividad))
continua2=input("Ingresa otra actividad para la misma fecha[s/n]:")

Cuando se terminan de cargar todas las actividades para una determinada


fecha se procede a insertar la lista en el diccionario:

agenda[fecha]=lista
continua1=input("Ingresa otra fecha[s/n]:")

Previo a salir de la función devolvemos la agenda ya cargada:

return agenda

Para imprimir todas las fechas y actividades por fecha también disponemos dos
ciclos repetitivos anidados, en este caso for in:

def imprimir(agenda):
print("Listado completa de la agenda")
for fecha in agenda:
print("Para la fecha:",fecha)
for hora,actividad in agenda[fecha]:
print(hora,actividad)

De forma similar para consultar las actividades de la agenda una determinada


fecha procedemos a ingresar la fecha y en el caso que haya una clave en el
diccionario con ese dato procedemos a recuperar la lista de actividades para
dicha fecha:

def consulta_fecha(agenda):
fecha=input("Ingrese la fecha que desea consultar:")
if fecha in agenda:
for hora,actividad in agenda[fecha]:
print(hora,actividad)
else:
print("No hay actividades agendadas para dicha fecha")

El bloque principal no difiere de problemas anteriores donde llamamos a las


tres funciones que previamente definimos:

# bloque principal

agenda=cargar()
imprimir(agenda)
consulta_fecha(agenda)

Problema propuesto
• Se desea almacenar los datos de 3 alumnos. Definir un diccionario cuya
clave sea el número de documento del alumno. Como valor almacenar
una lista con componentes de tipo tupla donde almacenamos nombre de
materia y su nota.

Crear las siguientes funciones:


1) Carga de los alumnos (de cada alumno solicitar su dni y los nombres
de las materias y sus notas)
2) Listado de todos los alumnos con sus notas
3) Consulta de un alumno por su dni, mostrar las materias que cursa y
sus notas.
Ver video
Solución

Retornar

36 - Funciones: parámetros mutables


e inmutables
En Python tenemos tipos de datos inmutables:

enteros
float
string
tuplas

Mutables:

listas
diccionarios

Esto tiene mucha importancia cuando enviamos a una función una variable
mutable, veremos con un ejemplo como podemos pasar como parámetro una
lista a una función y posteriormente cambiar su contenido y esto se vea
reflejado en la variable que le enviamos al llamarla.

Problema 1:
Confeccionar un programa que contenga las siguientes funciones:
1) Carga de una lista y retorno al bloque principal.
2) Fijar en cero todos los elementos de la lista que tengan un valor menor a 10.
3) Imprimir la lista
Programa: ejercicio166.py
Ver video

def cargar():
lista=[]
continua="s"
while continua=="s":
valor=int(input("Ingrese un valor:"))
lista.append(valor)
continua=input("Agrega otro elemento a la
lista[s/n]:")
return lista
def fijar_cero(li):
for x in range(len(li)):
if li[x]<10:
li[x]=0

def imprimir(lista):
for elemento in lista:
print(elemento,"-",sep="",end="")
print("")

# bloque principal

lista=cargar()
print("Lista antes de modificar")
imprimir(lista)
fijar_cero(lista)
print("Lista despues de modificar")
imprimir(lista)
La primer función permite la carga de una lista de enteros hasta que el
operador no desee cargar más valores:

def cargar():
lista=[]
continua="s"
while continua=="s":
valor=int(input("Ingrese un valor:"))
lista.append(valor)
continua=input("Agrega otro elemento a la lista[s/n]:")
return lista

Lo nuevo aparece en la función fijar_cero que recibe como parámetro una lista
llamada "li" y dentro de la función modificamos los elementos de la lista, estos
cambios luego se ven reflejados en la variable definida en el bloque principal
de nuestro programa:

def fijar_cero(li):
for x in range(len(li)):
if li[x]<10:
li[x]=0

Si ejecutamos este programa e ingresamos algunos elementos de la lista con


valores inferiores a 10 veremos luego que la variable global "lista" es
modificada:
Problema 2:
Confeccionar un programa que contenga las siguientes funciones:
1) Carga de una lista de 5 nombres.
2) Ordenar alfabéticamente la lista.
3) Imprimir la lista de nombres
Programa: ejercicio167.py
Ver video

def cargar():
nombres=[]
for x in range(5):
nom=input("Ingrese nombre:")
nombres.append(nom)
return nombres

def ordenar(nombres):
for k in range(4):
for x in range(4):
if nombres[x]>nombres[x+1]:
aux=nombres[x]
nombres[x]=nombres[x+1]
nombres[x+1]=aux

def imprimir(nombres):
for x in range(len(nombres)):
print(nombres[x]," ",end="")
# bloque principal

nombres=cargar()
ordenar(nombres)
imprimir(nombres)
En este problema tenemos que intercambiar los elementos de una lista y
dejarlos ordenados. La primer función para crear la lista y cargarla no presenta
nada nuevo a lo visto en problemas anteriores:

def cargar():
nombres=[]
for x in range(5):
nom=input("Ingrese nombre:")
nombres.append(nom)
return nombres

El algoritmo de ordenamiento lo vimos cuando solo conocíamos la


programación lineal, por lo que todas las variables eran globales. Ahora
tenemos que hacer el ordenamiento de la lista en una función y que se
modifique la variable que le pasamos desde el bloque principal:

def ordenar(nombres):
for k in range(4):
for x in range(4):
if nombres[x]>nombres[x+1]:
aux=nombres[x]
nombres[x]=nombres[x+1]
nombres[x+1]=aux

El parámetro "nombres" al ser modificado (nombres[x]=nombres[x+1] y


nombres[x+1]=aux) se modifica la variable global que le pasamos desde el
bloque principal:

# bloque principal
nombres=cargar()
ordenar(nombres)
imprimir(nombres)

Luego de ejecutarse la función "ordenar" llamamos a la función "imprimir"


pasando la variable "nombres" ya ordenada.
Veremos un último problema pasando y modificando una estructura de datos
tipo diccionario. Recordemos que listas y diccionarios son mutables en Python.
Cuando pasamos a una función como parámetro una lista o un diccionario
luego los cambios que sufre la estructura de datos se ven luego reflejadas en
las variables que se pasaron desde el bloque principal.

Problema 3:
Confeccionar un programa que almacene en un diccionario como clave el
nombre de un contacto y como valor su número telefónico:
1) Carga de contactos y su número telefónico.
2) Pemitir modificar el número telefónico. Se ingresa el nombre del contacto
para su búsqueda.
3) Imprimir la lista completa de contactos con sus números telefónicos.
Programa: ejercicio168.py
Ver video

def cargar():
contactos={}
continua="s"
while continua=="s":
nombre=input("Ingrese el nombre del conta
cto:")
telefono=input("Ingrese el numero de tele
fono:")
contactos[nombre]=telefono
continua=input("Ingresa otro contacto[s/n
]?:")
return contactos
def modificar_telefono(contactos):
nombre=input("Ingrese el nombre de contacto a
modificar el telefono:")
if nombre in contactos:
telefono=input("Ingrese el nuevo numero t
elefonico")
contactos[nombre]=telefono
else:
print("No existe un contacto con el nombr
e ingresado")

def imprimir(contactos):
print("Listado de todos los contactos")
for nombre in contactos:
print(nombre,contactos[nombre])

# bloque principal

contactos=cargar()
modificar_telefono(contactos)
imprimir(contactos)
La primer función nos permite cargar los nombres de contactos con sus
respectivos teléfonos en un diccionario llamado "contactos", la función retorna
este diccionario y se almacena posteriormente en una variable global:
def cargar():
contactos={}
continua="s"
while continua=="s":
nombre=input("Ingrese el nombre del contacto:")
telefono=input("Ingrese el numero de telefono:")
contactos[nombre]=telefono
continua=input("Ingresa otro contacto[s/n]?:")
return contactos

En el bloque principal se guarda en:

# bloque principal

contactos=cargar()

La función "modificar_telefono" recibe como parámetro el diccionario


"contactos", solicita la carga de un contacto, en el caso que exita se procede a
solicitar el nuevo teléfono y modificar el diccionario:

def modificar_telefono(contactos):
nombre=input("Ingrese el nombre de contacto a modificar el telefono:")
if nombre in contactos:
telefono=input("Ingrese el nuevo numero telefonico")
contactos[nombre]=telefono
else:
print("No existe un contacto con el nombre ingresado")

Con la modificación del parámetro en la función "modificar_telefono" se está


modificando la variable global que le pasamos desde el bloque principal:

# bloque principal

contactos=cargar()
modificar_telefono(contactos)

Ahora cuando imprimimos el diccionario podemos ver que el teléfono aparece


modificado:
def imprimir(contactos):
print("Listado de todos los contactos")
for nombre in contactos:
print(nombre,contactos[nombre])

Problema propuesto
• Crear un diccionario en Python para almacenar los datos de empleados
de una empresa. La clave será su número de legajo y en su valor
almacenar una lista con el nombre, profesión y sueldo.

Desarrollar las siguientes funciones:


1) Carga de datos de empleados.
2) Permitir modificar el sueldo de un empleado. Ingresamos su número
de legajo para buscarlo.
3) Mostrar todos los datos de empleados que tienen una profesión de
"analista de sistemas"
Ver video
Solución

Retornar

37 - Porciones de listas, tuplas y


cadenas de caracteres
El lenguaje Python nos facilita una sintaxis muy sencilla par recuperar un trozo
de una lista, tupla o cadena de caracteres.
Veremos con una serie de ejemplos como podemos rescatar uno o varios
elementos de las estructuras de datos mencionadas.
Programa: ejercicio170.py
Ver video

lista1=[0,1,2,3,4,5,6]
lista2=lista1[2:5]
print(lista2) # 2,3,4
lista3=lista1[1:3]
print(lista3) # 1,2
lista4=lista1[:3]
print(lista4) # 0,1,2
lista5=lista1[2:]
print(lista5) # 2,3,4,5,6
Para recuperar una "porción" o trozo de una lista debemos indicar en el
subíndice dos valores separados por el caracter ":".
Del lado izquierdo indicamos a partir de que elementos queremos recuperar y
del lado derecho hasta cual posición sin incluir dicho valor.
Por ejemplo con la sintaxis:

lista1=[0,1,2,3,4,5,6]
lista2=lista1[2:5]
print(lista2) # 2,3,4

Estamos recuperando de la posición 2 hasta la 5 sin incluirla.


También es posible no indicar alguno de los dos valores:

lista4=lista1[:3]
print(lista4) # 0,1,2

Si no indicamos el primer valor estamos diciendo que queremos recuperar


desde el principio de la lista hasta la posición menos uno indicada después de
los dos puntos.
En cambio si no indicamos el valor después de los dos puntos se recupera
hasta el final de la lista:

lista5=lista1[2:]
print(lista5) # 2,3,4,5,6

Problema 1:
Confeccionar una función que le enviemos un número de mes como parámetro
y nos retorne una tupla con todos los nombres de meses que faltan hasta fin de
año.
Programa: ejercicio171.py
Ver video

def meses_faltantes(numeromes):
meses=('enero','febrero','marzo','abril','may
o','junio','julio','agosto','septiembre','octubre
','noviembre','diciembre')
return meses[numeromes:]

# bloque principal

print("Imprimir los nombres de meses que faltan h


asta fin de año")
numeromes=int(input("Ingrese el numero de mes:"))
mesesfalta=meses_faltantes(numeromes)
print(mesesfalta)
Utilizamos el concepto de porciones que nos brinda Python para recuperar en
forma muy sencilla un trozo de una tupla. La función meses_faltantes recibe
como parámetro un entero y retorna una tupla:

def meses_faltantes(numeromes):
meses=('enero','febrero','marzo','abril','mayo','junio','julio','agosto','se
ptiembre','octubre','noviembre','diciembre')
return meses[numeromes:]

Como vemos generamos una tupla a partir del valor "numeromes" hasta el final
de la tupla:

return meses[numeromes:]
En el bloque principal del programa cargamos el número de mes, llamamos a
la función e imprimimos la tupla devuelta por la función:

# bloque principal

print("Imprimir los nombres de meses que faltan hasta fin de año")


numeromes=int(input("Ingrese el numero de mes:"))
mesesfalta=meses_faltantes(numeromes)
print(mesesfalta)

Hay que tener en cuenta que el concepto de "porciones" se puede aplicar en


forma indistinta a listas, tuplas y cadenas de caracteres.

Problema 2:
Confeccionar una función que reciba una cadena de caracteres y nos devuelva
los tres primeros.
En el bloque principal del programa definir una tupla con los nombres de
meses. Mostrar por pantalla los primeros tres caracteres de cada mes.
Programa: ejercicio172.py
Ver video

def primeros_tres(cadena):
return cadena[:3];

# bloque principal

meses=('enero','febrero','marzo','abril','mayo','
junio','julio','agosto','septiembre','octubre','n
oviembre','diciembre')
for x in meses:
print(primeros_tres(x))
La función primeros_tres recibe un string y retorna los tres primeros caracteres:

def primeros_tres(cadena):
return cadena[:3];

En el bloque principal definimos la tupla y luego la recorremos con un for


llamando en la misma a la función que acabamos de crear:

meses=('enero','febrero','marzo','abril','mayo','junio','julio','agosto','septie
mbre','octubre','noviembre','diciembre')
for x in meses:
print(primeros_tres(x))

Acotaciones
El comando "del" de Python para la eliminación de componentes de una lista
también funcionan con la sintaxis de porciones:

del(lista[2:5]) # eliminamos los elementos de las posiciones 2,3 y 4

Problemas propuestos
• Realizar un programa que contenga las siguientes funciones:
1) Carga de una lista de 10 enteros.
2) Recibir una lista y retornar otra con la primer mitad (se sabe que
siempre llega una lista con una cantidad par de elementos)
3) Imprimir una lista.

Ver video

• Cargar una cadena por teclado luego:


1) Imprimir los dos primeros caracteres.
2) Imprimir los dos últimos
3) Imprimir todos menos el primero y el último caracter.

Ver video
Solución

Retornar

38 - Indices negativos en listas, tuplas


y cadenas de caracteres
Hemos visto que para acceder a un elemento de una lista, tupla o cadena de
caracteres debemos indicar mediante un subíndice que comienza a numerarse
a partir de cero.
También hemos visto el concepto anterior que podemos generar otra lista,
tupla o cadena de caracteres indicando una porción con el caracter ":"
Ahora veremos que podemos utilizar un valor negativo para acceder a un
elemento de la estructura de datos.
Programa: ejercicio175.py
Ver video

lista1=[0,1,2,3,4,5,6]
print(lista1[-1]) # 6
print(lista1[-2]) # 5
En Python podemos acceder fácilmente al último elemento de la secuencia
indicando un subíndice -1:

print(lista1[-1]) # 6

Luego el anteúltimo se accede con la sintaxis:

print(lista1[-2]) # 5

Problema 1:
Confeccionar una función que reciba una palabra y verifique si es capicúa (es
decir que se lee igual de izquierda a derecha que de derecha a izquierda)
Programa: ejercicio176.py
Ver video

def capicua(cadena):
indice=-1
iguales=0
for x in range(0,len(cadena)//2):
if cadena[x]==cadena[indice]:
iguales=iguales+1
indice=indice-1
print(cadena)
if iguales==(len(cadena)//2):
print("Es capicua")
else:
print("No es capicua")

# bloque principal

capicua("neuquen")
capicua("casa")
Disponemos un contador que comience en -1 llamado indice y otro contador
para las coincidencias:

def capicua(cadena):
indice=-1
iguales=0

Un for que se repita tantas veces como caracteres tenga la palabra dividido 2:

for x in range(0,len(cadena)//2):

Dentro del for verificamos si el caracter del principio de lista coincide con el
caracter del fin de la lista, si es así incrementamos el contador de
coincidencias:

if cadena[x]==cadena[indice]:
iguales=iguales+1
indice=indice-1

Cuando sale del for si la cantidad de coincidencias es igual a la mitad de la


cadena luego podemos inferir que la palabra es capicúa:

if iguales==(len(cadena)//2):
print("Es capicua")
else:
print("No es capicua")
Problemas propuestos
• Cargar una cadena de caracteres por teclado. Mostrar la cadena del final
al principio utilizando subíndices negativos.

• Confeccionar un programa con las siguientes funciones:


1) Cargar una lista con 5 palabras.
2) Intercambiar la primer palabra con la última.
3) Imprimir la lista

Ver video
Solución

Retornar

39 - Biblioteca estándar de Python


Todos los conceptos que hemos visto hasta ahora los hemos resuelto
utilizando solo la sintaxis que nos provee Python y un conjunto de funciones
básicas que se incluyen automáticamente como por ejemplo son print, range,
len etc.
En Python se incluye una biblioteca extra de funciones, variables, clases etc.
que nos facilitan la resolución de problemas en una gran diversidad de áreas
como matemáticas, estadísticas, compresión de datos, internet, interfaces
visuales etc.
Veremos en este concepto como se importa un módulo de la biblioteca
estándar y como se accede a su funcionalidad.

Problema 1:
Confeccionar un programa que simule tirar dos dados y luego muestre los
valores que salieron. Imprimir un mensaje que ganó si la suma de los mismos
es igual a 7.
Para resolver este problema requerimos un algoritmo para que se genere un
valor aleatorio entre 1 y 6. Como la generación de valores aleatorios es un
tema muy frecuente la biblioteca estándar de Python incluye un módulo que
nos resuelve la generación de valores aleatorios.
Programa: ejercicio179.py
Ver video

import random

dado1=random.randint(1,6)
dado2=random.randint(1,6)
print("Primer dado:",dado1)
print("Segundo dado:",dado2)
suma=dado1+dado2
if suma==7:
print("Gano")
else:
print("Perdio")

Para importar un módulo de la biblioteca estándar de Python utilizamos la


palabra clave import seguida por el nombre del módulo que necesitamos
importar:

import random

Como dijimos la biblioteca estándar de Python se instala junto con Python.


Si disponemos un nombre de módulo inexistente aparecerá un error:

Traceback (most recent call last):


File "C:/programaspython/ejercicio179.py", line 1, in
import ran
ImportError: No module named 'ran'

Para acceder a todas las funciones contenidas en el módulo random es


necesario primero importar el módulo y luego dentro del algoritmo de nuestro
programa anteceder primero el nombre del módulo y seguidamente la función
que queremos acceder:
dado1=random.randint(1,6)

Si tratamos de acceder directamente al nombre de la función sin disponer el


nombre del módulo se produce un error:

Traceback (most recent call last):


File "C:/programaspython/ejercicio179.py", line 3, in
dado1=randint(1,6)
NameError: name 'randint' is not defined

Este error se produce porque la función randint no es una función integrada en


Python como print, range, len etc.
Entonces la sintaxis para acceder a la funcionalidad de un módulo requiere que
dispongamos primero el nombre del módulo y seguidamente el nombre de la
función.
Como podemos imaginar la función randint retorna un valor aleatorio
comprendido entre los dos valores indicados en los parámetros.
La ejecución del programa tiene una salida similar a esta:
Problema 2:
Desarrollar un programa que cargue una lista con 10 enteros.
Cargar los valores aleatorios con números enteros comprendidos entre 0 y
1000.
Mostrar la lista por pantalla.
Luego mezclar los elementos de la lista y volver a mostrarlo.
Programa: ejercicio180.py
Ver video

import random
def cargar():
lista=[]
for x in range(10):
lista.append(random.randint(0,1000))
return lista

def imprimir(lista):
print(lista)

def mezclar(lista):
random.shuffle(lista)

# bloque principal

lista=cargar()
print("Lista generada aleatoriamente")
imprimir(lista)
mezclar(lista)
print("La misma lista luego de mezclar")
imprimir(lista)
No hay ningún problema de llamar a las funciones de un módulo dentro de una
función propia siempre y cuando indiquemos el import respectivo:

import random
def cargar():
lista=[]
for x in range(10):
lista.append(random.randint(0,1000))
return lista

El módulo random cuenta con otra función llamada shuffle que le pasamos
como parámetro una lista y nos la devuelve con los elementos mezclados
(pensemos esto nos podría servir si estamos desarrollando un juego de naipes
y necesitamos mezclarlos):

def mezclar(lista):
random.shuffle(lista)

Desde el bloque principal procedemos a llamar a las funciones que hemos


codificado:

# bloque principal

lista=cargar()
print("Lista generada aleatoriamente")
imprimir(lista)
mezclar(lista)
print("La misma lista luego de mezclar")
imprimir(lista)

En la documentación oficial de Python podemos consultar todas las funciones


que nos provee el módulo random random.
Y en general podemos también consultar todos los módulos de la Biblioteca
estándar de Python.

Problemas propuestos
• Confeccionar un programa que genere un número aleatorio entre 1 y 100
y no se muestre.
El operador debe tratar de adivinar el número ingresado.
Cada vez que ingrese un número mostrar un mensaje "Gano" si es igual
al generado o "El número aleatorio es mayor" o "El número aleatorio es
menor".
Mostrar cuando gana el jugador cuantos intentos necesitó.

Ver video

• Confeccionar una programa con las siguientes funciones:


1) Generar una lista con 4 elementos enteros aleatorios comprendidos
entre 1 y 3. Agregar un quinto elemento con un 1.
2) Controlar que el primer elemento de la lista sea un 1, en el caso que
haya un 2 o 3 mezclar la lista y volver a controlar hasta que haya un 1.
3) Imprimir la lista.

Ver video
Solución

Retornar

40 - Importar algunas funcionalidades


de un módulo de la biblioteca
estándar de Python
Hemos visto que para importar toda la funcionalidad de un módulo de la
Biblioteca estándar de Python utilizamos la palabra clave import y
seguidamente el nombre del módulo:

import random

Con esa sintaxis todas las funcionalidades del módulo "random" pueden ser
accedidas desde nuestro módulo.
Ahora veremos que en Python tenemos otra sintaxis para las situaciones que
queremos acceder a una o pocas funcionalidades de un módulo.
Por ejemplo si queremos acceder solo a la función randint del módulo random
en Python lo podemos expresar con la siguiente sintaxis:

from random import randint


Utilizamos la palabra clave from y seguidamente el nombre del módulo de
donde queremos importar funcionalidades del mismo. Luego indicamos la
palabra clave import y la funcionalidad que queremos importar, en nuestro
ejemplo la función randint.
También cambia como utilizamos la función randint dentro de nuestro módulo:

valor=randint(1,10)
print(valor)

Como vemos no le antecedemos ningún nombre de módulo y hacemos


referencia directamente a la función importada.
Si necesitamos importar más de una funcionalidad de un módulo debemos
separar por comas las funcionalidades importadas:

from random import randint,shuffle

Problema 1:
Confeccionar un programa que solicite la carga de un valor entero por teclado y
luego nos muestre la raíz cuadrada del número y el valor elevado al cubo.
Para resolver este problema utilizaremos dos funcionalidades que nos provee
el módulo math de la biblioteca estándar de Python. Podemos consultar el
módulo math aquí
Programa: ejercicio183.py
Ver video

from math import sqrt, pow

valor=int(input("Ingrese un valor entero:"))


r1=sqrt(valor)
r2=pow(valor,3)
print("La raiz cuadrada es",r1)
print("El cubo es",r2)
El módulo math tiene dos funciones llamadas sqrt (para obtener la raíz
cuadrada) y la función pow para elevar un valor a cierta potencia.
Utilizamos la sintaxis para importar solo dichas dos funcionalidades del módulo
math:

from math import sqrt, pow

Una vez importadas las dos funciones podemos hacer uso de las mismas en
nuestro programa indicando directamente su nombre:

r1=sqrt(valor)

Lo mismo para llamar la función pow:

r2=pow(valor,3)

Definición de alias para una funcionalidad


Podemos definir un nombre distinto para una funcionalidad que importamos de
otro módulo. Esto puede tener como objetivo que nuestro programa sea más
legible o evitar que un nombre de función que importamos colisione con un
nombre de función de nuestro propio módulo.
Resolveremos el mismo problema anterior pero definiendo dos alias para las
funciones sqrt y pow del módulo math.
Programa: ejercicio184.py
Ver video

from math import sqrt as raiz, pow as elevar

valor=int(input("Ingrese un valor entero:"))


r1=raiz(valor)
r2=elevar(valor,3)
print("La raiz cuadrada es",r1)
print("El cubo es",r2)
Como vemos para definir un alias a una funcionalidad que importamos de un
módulo debemos disponer la palabra clave as seguida del nuevo nombre:

from math import sqrt as raiz, pow as elevar


Luego para utilizar la funcionalidad que importamos debemos hacerlo mediante
el alias y no con el nombre definido en el módulo que importamos:

r1=raiz(valor)
r2=elevar(valor,3)

Problema propuesto
• Calcular el factorial de un número ingresado por teclado.
El factorial de un número es la cantidad que resulta de la multiplicación
de determinado número natural por todos los números naturales que le
anteceden excluyendo el cero. Por ejemplo el factorial de 4 es 24, que
resulta de multiplicar 4*3*2*1.
No hay que implementar el algoritmo para calcular el factorial sino hay
que importar dicha funcionalidad del módulo math.
El módulo math tiene una función llamada factorial que recibe como
parámetro un entero del que necesitamos que nos retorne el factorial.
Solo importar la funcionalidad factorial del módulo math de la biblioteca
estándar de Python.

Ver video
Solución

Retornar

41 - Aplicaciones propias con varios


módulos
A medida que una aplicación sea más grande vimos que disponer todo el
algoritmo en forma secuencial es difícil de mantener y desarrollar. Para eso
vimos que podemos resolver por partes utilizando funciones.
Pero siempre dispusimos todas las funciones en un único archivo.
Pensemos que nuestro problema podría ser lo suficientemente complejo y
grande que también por más que lo dividamos en funciones un único archivo
sea complejo de mantener.
En Python podemos agrupar funciones en distintos archivos (módulos) y luego
importarlos en otros módulos.
Así como importamos los módulos de la biblioteca estándar de Python
podemos importar otros módulos que codifiquemos nosotros.

Problema 1:
Confeccionar una aplicación que permita cargar por teclado una lista de
enteros, obtener y mostrar el mayor y calcular su suma. Definir un módulo con
las funciones de carga, identificar el mayor y sumar. En el módulo principal del
programa importar el otro módulo y llamar a sus funciones.
Para ser un poco más ordenados crearemos una carpeta llamada proyecto1 y
dentro de la misma crearemos los dos módulos llamados:

operacioneslista.py
principal.py

El módulo operacioneslista.py contiene todas las funciones que nos permiten


cargar una lista, imprimir el mayor de una lista y sumar todos los elementos y
mostrar dicho valor.
módulo: operacioneslista.py
Ver video

def cargar():
lista=[]
for x in range(5):
valor=int(input("Ingrese valor:"))
lista.append(valor)
return lista

def imprimir_mayor(lista):
may=lista[0]
for x in range(1,5):
if lista[x]>may:
may=lista[x]
print("Mayor de la lista",may)

def imprimir_suma(lista):
suma=0
for elemento in lista:
suma=suma+elemento
print("Suma de todos sus elementos",suma)
El segundo archivo y desde donde realmente arrancará nuestro programa es el
módulo principal.py
módulo: principal.py

import operacioneslista

lista=operacioneslista.cargar()
operacioneslista.imprimir_mayor(lista)
operacioneslista.imprimir_suma(lista)
Es importante indicar que cuando queremos ejecutar nuestro programa
tenemos que abrir el archivo principal.py y elegir la opción "Run Module" o
presionar la tecla "F5".
Como podemos ver nuestro módulo principal solo tiene cuatro líneas:

import operacioneslista

lista=operacioneslista.cargar()
operacioneslista.imprimir_mayor(lista)
operacioneslista.imprimir_suma(lista)

Primero importamos el módulo operacioneslista y seguidamente llamamos a


las funciones de cargar, imprimir_mayor y imprimir_suma. Recordar que
debemos anteceder el nombre del módulo donde están definidas.
Podemos ver luego de ejecutarlo a nuestro programa que en la carpeta de
nuestro proyecto1 además de los archivo operacioneslista.py y principal.py hay
una carpeta llamada __pycache__ con un archivo con extensión *.pyc
(operacioneslista.cpython-35.pyc) Este archivo lo crea automáticamente el
Python cuando ejecutamos por primera vez nuestro programa y tiene por
objetivo hacer más eficiente las ejecuciones futuras del programa.
Por ahora dispondremos todos los módulos de nuestro proyecto en la misma
carpeta.

Esta característica de Python de poder disponer funcionalidades en distintos


archivos es fundamental para cuando hay que desarrollar programas en los
cuales intervienen un conjunto de programadores. Se posibilita asignar a cada
programador distintas funcionalidades y que se implementen en distintos
módulos.
También nos facilita el implementar módulos con funcionalidades que pueden
ser reutilizadas en otros proyectos, así como sucede con la biblioteca estándar
de Python.

Problema 2:
Confeccionar un módulo que implemente dos funciones, una que retorne el
mayor de dos enteros y otra que retorne el menor de dos enteros.
En el módulo principal importar solo la función que retorne el mayor, luego
cargar dos enteros y mostrar el mayor de ellos
Crear una carpeta llamada proyecto2 y dentro de la misma crear dos módulos
llamados:

mayormenor.py
principal.py

El módulo mayormenor.py contiene las dos funciones que identifican el mayor


de dos enteros por un lado y el menor de dos enteros.
módulo: mayormenor.py
Ver video
def mayor(x1,x2):
if x1>x2:
return x1
else:
return x2

def menor(x1,x2):
if x1<x2:
return x1
else:
return x2
Por otro lado el programa principal que importa solo la función mayor es:
módulo: principal.py

from mayormenor import mayor

valor1=int(input("Ingrese primer valor:"))


valor2=int(input("Ingrese segundo valor:"))
print("El mayor de los dos valores es",mayor(valo
r1,valor2))
Esta sintaxis de importar funcionalidades particulares de un módulo la vimos
anteriormente con la biblioteca estándar de Python.

Retornar
42 - Conceptos de programación
orientada a objetos
Python nos permite utilizar distintas metodologías de programación. Hemos
implementado inicialmente programas utilizando la programación lineal, luego
vimos funciones y trabajamos con programación estructurada.
Ahora introduciremos los conceptos de programación orientada a objetos. A
partir de este concepto mostraremos en forma sencilla la metodología de
Programación Orientada a Objetos.
Se irán introduciendo conceptos de objeto, clase, atributo, método etc. y de
todos estos temas se irán planteando problemas resueltos.
Prácticamente todos los lenguajes desarrollados en los últimos 25 años
implementan la posibilidad de trabajar con POO (Programación Orientada a
Objetos)
El lenguaje Python tiene la característica de permitir programar con las
siguientes metodologías:

• Programación Lineal: Es cuando desarrollamos todo el código sin emplear


funciones. El código es una secuencia lineal de comando.

• Programación Estructurada: Es cuando planteamos funciones que agrupan


actividades a desarrollar y luego dentro del programa llamamos a dichas
funciones que pueden estar dentro del mismo archivo (módulo) o en una
librería separada.

• Programación Orientada a Objetos: Es cuando planteamos clases y


definimos objetos de las mismas (Este es el objetivo de los próximos
conceptos, aprender la metodología de programación orientada a objetos y
la sintaxis particular de Python para la POO)

Conceptos básicos de Objetos


Un objeto es una entidad independiente con sus propios datos y programación.
Las ventanas, menúes, carpetas de archivos pueden ser identificados como
objetos; el motor de un auto también es considerado un objeto, en este caso,
sus datos (atributos) describen sus características físicas y su programación
(métodos) describen el funcionamiento interno y su interrelación con otras
partes del automóvil (también objetos).
El concepto renovador de la tecnología de Orientación a Objetos es la suma de
funciones a elementos de datos, a esta unión se le llama encapsulamiento.
Por ejemplo, un objeto Auto contiene ruedas, motor, velocidad, color, etc,
llamados atributos. Encapsulados con estos datos se encuentran los métodos
para arrancar, detenerse, dobla, frenar etc.
La responsabilidad de un objeto auto consiste en realizar las acciones
apropiadas y mantener actualizados sus datos internos.
Cuando otra parte del programa (otros objetos) necesitan que el auto realice
alguna de estas tareas (por ejemplo, arrancar) le envía un mensaje. A estos
objetos que envían mensajes no les interesa la manera en que el objeto auto
lleva a cabo sus tareas ni las estructuras de datos que maneja, por ello, están
ocultos.
Entonces, un objeto contiene información pública, lo que necesitan los otros
objetos para interactuar con él e información privada, interna, lo que necesita el
objeto para operar y que es irrelevante para los otros objetos de la aplicación.

Retornar

43 - Declaración de una clase y


creación de objetos
La programación orientada a objetos se basa en la definición de clases; a
diferencia de la programación estructurada, que está centrada en las
funciones.
Una clase es un molde del que luego se pueden crear múltiples objetos, con
similares características.
Un poco más abajo se define una clase Persona y luego se crean dos objetos
de dicha clase.
Una clase es una plantilla (molde), que define atributos (lo que conocemos
como variables) y métodos (lo que conocemos como funciones).
La clase define los atributos y métodos comunes a los objetos de ese tipo, pero
luego, cada objeto tendrá sus propios valores y compartirán las mismas
funciones.
Debemos declarar una clase antes de poder crear objetos (instancias) de esa
clase. Al crear un objeto de una clase, se dice que se crea una instancia de la
clase o un objeto propiamente dicho.

Problema 1:
Implementaremos una clase llamada Persona que tendrá como atributo
(variable) su nombre y dos métodos (funciones), uno de dichos métodos
inicializará el atributo nombre y el siguiente método mostrará en la pantalla el
contenido del mismo.
Definir dos objetos de la clase Persona.
Ver video
Programa: ejercicio186.py

class Persona:

def inicializar(self,nom):
self.nombre=nom

def imprimir(self):
print("Nombre",self.nombre)

# bloque principal

persona1=Persona()
persona1.inicializar("Pedro")
persona1.imprimir()

persona2=Persona()
persona2.inicializar("Carla")
persona2.imprimir()
Siempre conviene buscar un nombre de clase lo más próximo a lo que
representa. La palabra clave para declarar la clase es class, seguidamente el
nombre de la clase y luego dos puntos.
Los métodos de una clase se definen utilizando la misma sintaxis que para la
definición de funciones.
Como veremos todo método tiene como primer parámetro el identificador self
que tiene la referencia del objeto que llamó al método.
Luego dentro del método diferenciamos los atributos del objeto antecediendo el
identificador self:

self.nombre=nom

Con la asignación previa almacenamos en el atributo nombre el parámetro


nom, los atributos siguen existiendo cuando finaliza la ejecución del método.
Por ello cuando se ejecuta el método imprimir podemos mostrar el nombre que
cargamos en el primer método.
Decíamos que una clase es un molde que nos permite definir objetos. Ahora
veamos cual es la sintaxis para la creación de objetos de la clase Persona:

# bloque principal

persona1=Persona()
persona1.inicializar("Pedro")
persona1.imprimir()

persona2=Persona()
persona2.inicializar("Carla")
persona2.imprimir()

Definimos un objeto llamado persona1 y lo creamos asignándole el nombre de


la clase con paréntesis abierto y cerrado al final (como cuando llamamos a una
función)
Luego para llamar a los métodos debemos disponer luego del nombre del
objeto el operador . y por último el nombre del método (función)
En el caso que tenga parámetros se los enviamos (salvo el primer parámetro
(self) que el mismo Python se encarga de enviar la referencia del objeto que se
creó):

persona1.inicializar("Pedro")

También podemos definir tantos objetos de la clase Persona como sean


necesarios para nuestro algoritmo:
persona2=Persona()
persona2.inicializar("Carla")
persona2.imprimir()

La declaración de clases es una de las ventajas fundamentales de la


Programación Orientada a Objetos (POO), es decir reutilización de código
(gracias a que está encapsulada en clases) es muy sencilla.

Problema 2:
Implementar una clase llamada Alumno que tenga como atributos su nombre y
su nota. Definir los métodos para inicializar sus atributos, imprimirlos y mostrar
un mensaje si está regular (nota mayor o igual a 4)
Definir dos objetos de la clase Alumno.
Programa: ejercicio187.py
Ver video

class Alumno:

def inicializar(self,nombre,nota):
self.nombre=nombre
self.nota=nota

def imprimir(self):
print("Nombre:",self.nombre)
print("Nota:",self.nota)

def mostrar_estado(self):
if self.nota>=4:
print("Regular")
else:
print("Libre")
# bloque principal

alumno1=Alumno()
alumno1.inicializar("diego",2)
alumno1.imprimir()
alumno1.mostrar_estado()

alumno2=Alumno()
alumno2.inicializar("ana",10)
alumno2.imprimir()
alumno2.mostrar_estado()
Declaramos la clase Alumno y definimos sus tres métodos, en el método
inicializar llegan como parámetros a parte del self el nombre y nota del alumno:

def inicializar(self,nombre,nota):
self.nombre=nombre
self.nota=nota

No hay problema que los atributos se llamen iguales a los parámetros ya que
siempre hay que anteceder la palabra "self" al nombre del atributo:

self.nombre=nombre

Tener en cuenta que cuando se crean los atributos en el método inicializar


luego podemos acceder a los mismos en los otros métodos de la clase, por
ejemplo en el método mostrar_estado verificamos el valor almacenado en el
atributo nota:

def mostrar_estado(self):
if self.nota>=4:
print("Regular")
else:
print("Libre")

Decimos que una clase es un molde que nos permite crear luego objetos de
dicha clase, en este problema el molde Alumno lo utilizamos para crear dos
objetos de dicha clase:

# bloque principal

alumno1=Alumno()
alumno1.inicializar("diego",2)
alumno1.imprimir()
alumno1.mostrar_estado()

alumno2=Alumno()
alumno2.inicializar("ana",10)
alumno2.imprimir()
alumno2.mostrar_estado()

Es fundamental la definición de objetos de una clase para que haya tenido


sentido la declaración de dicha clase.

Problemas propuestos
• Confeccionar una clase que permita carga el nombre y la edad de una
persona. Mostrar los datos cargados. Imprimir un mensaje si es mayor
de edad (edad>=18)

Ver video

• Desarrollar un programa que cargue los lados de un triángulo e


implemente los siguientes métodos: inicializar los atributos, imprimir el
valor del lado mayor y otro método que muestre si es equilátero o no. El
nombre de la clase llamarla Triangulo.

Ver video
Solución

Retornar
44 - Método __init__ de la clase
El método __init__ es un método especial de una clase en Python. El objetivo
fundamental del método __init__ es inicializar los atributos del objeto que
creamos.
Básicamente el método __init__ remplaza al método inicializar que habíamos
hecho en el concepto anterior.
Las ventajas de implementar el método __init__ en lugar del método inicializar
son:

1. El método __init__ es el primer método que se ejecuta cuando se crea


un objeto.
2. El método __init__ se llama automáticamente. Es decir es imposible de
olvidarse de llamarlo ya que se llamará automáticamente.
3. Quien utiliza POO en Python (Programación Orientada a Objetos)
conoce el objetivo de este método.

Otras características del método __init__ son:

• Se ejecuta inmediatamente luego de crear un objeto.

• El método __init__ no puede retornar dato.

• el método __init__ puede recibir parámetros que se utilizan normalmente


para inicializar atributos.

• El método __init__ es un método opcional, de todos modos es muy


común declararlo.

Veamos la sintaxis del constructor:

def __init__([parámetros]):
[algoritmo]

Debemos definir un método llamado __init__ (es decir utilizamos dos


caracteres de subrayado, la palabra init y seguidamente otros dos caracteres
de subrayado).

Problema 1:
Confeccionar una clase que represente un empleado. Definir como atributos su
nombre y su sueldo. En el método __init__ cargar los atributos por teclado y
luego en otro método imprimir sus datos y por último uno que imprima un
mensaje si debe pagar impuestos (si el sueldo supera a 3000)
Programa: ejercicio190.py
Ver video

class Empleado:

def __init__(self):
self.nombre=input("Ingrese el nombre del
empleado:")
self.sueldo=float(input("Ingrese el sueld
o:"))

def imprimir(self):
print("Nombre:",self.nombre)
print("Sueldo:",self.sueldo)

def paga_impuestos(self):
if self.sueldo>3000:
print("Debe pagar impuestos")
else:
print("No paga impuestos")

# bloque principal

empleado1=Empleado()
empleado1.imprimir()
empleado1.paga_impuestos()
Definimos el método __init__ donde cargamos por teclado el nombre del
empleado y su sueldo:

def __init__(self):
self.nombre=input("Ingrese el nombre del empleado:")
self.sueldo=float(input("Ingrese el sueldo:"))

Este método se ejecuta inmediatamente luego que se crea un objeto de la


clase Empleado:

empleado1=Empleado()

Como vemos no llamamos directamente al método __init__ sino que se llama


automáticamente.
Los otros dos métodos tienen por objeto mostrar los datos del empleado y
mostrar una leyenda si paga impuestos o no:

def imprimir(self):
print("Nombre:",self.nombre)
print("Sueldo:",self.sueldo)

def paga_impuestos(self):
if self.sueldo>3000:
print("Debe pagar impuestos")
else:
print("No paga impuestos")

Desde el bloque principal donde creamos un objeto de la clase Empleado


debemos llamar explícitamente a estos dos métodos:

empleado1.imprimir()
empleado1.paga_impuestos()

Problema 2:
Desarrollar una clase que represente un punto en el plano y tenga los
siguientes métodos: inicializar los valores de x e y que llegan como parámetros,
imprimir en que cuadrante se encuentra dicho punto (concepto matemático,
primer cuadrante si x e y son positivas, si x<0 e y>0 segundo cuadrante, etc.)
Programa: ejercicio191.py
Ver video

class Punto:

def __init__(self,x,y):
self.x=x
self.y=y

def imprimir(self):
print("Coordenada del punto")
print("(",self.x,",",self.y,")")

def imprimir_cuadrante(self):
if self.x>0 and self.y>0:
print("Primer cuadrange")
else:
if self.x<0 and self.y>0:
print("Segundo cuadrante")
else:
if self.x<0 and self.y<0:
print("Tercer cuadrante")
else:
if self.x>0 and self.y<0:
print("Cuarto cuadrante")
# bloque principal

punto1=Punto(10,-2)
punto1.imprimir()
punto1.imprimir_cuadrante()
En este problema el método __init__ aparte del parámetro self que siempre va
tenemos otros dos parámetros:

def __init__(self,x,y):
self.x=x
self.y=y

Desde el bloque principal donde creamos un objeto de la clase Punto pasamos


los datos a los parámetros:

punto1=Punto(10,-2)

Recordemos que pasamos dos parámetros aunque el método __init__ recibe


3. El parámetro self recibe la referencia de la variable punto1 (es decir el objeto
propiamente dicho)

Problemas propuestos
• Desarrollar una clase que represente un Cuadrado y tenga los siguientes
métodos: inicializar el valor del lado llegando como parámetro al método
__init__ (definir un atributo llamado lado), imprimir su perímetro y su
superficie.

Ver video

• Implementar la clase Operaciones. Se deben cargar dos valores enteros


por teclado en el método __init__, calcular su suma, resta, multiplicación
y división, cada una en un método, imprimir dichos resultados.

Ver video
Solución
Retornar

45 - Llamada de métodos desde otro


método de la misma clase
Hasta ahora todos los problemas planteados hemos llamado a los métodos
desde donde definimos un objeto de dicha clase, por ejemplo:

empleado1=Empleado("diego",2000)
empleado1.paga_impuestos()

Utilizamos la sintaxis:

[nombre del objeto].[nombre del método]

Es decir antecedemos al nombre del método el nombre del objeto y el operador


punto
Ahora bien que pasa si queremos llamar dentro de la clase a otro método que
pertenece a la misma clase, la sintaxis es la siguiente:

self.[nombre del método]

Es importante tener en cuenta que esto solo se puede hacer cuando estamos
dentro de la misma clase.

Problema 1:
Plantear una clase Operaciones que solicite en el método __init__ la carga de
dos enteros e inmediatamente muestre su suma, resta, multiplicación y
división. Hacer cada operación en otro método de la clase Operación y
llamarlos desde el mismo método __init__
Programa: ejercicio194.py
Ver video

class Operacion:
def __init__(self):
self.valor1=int(input("Ingrese primer val
or:"))
self.valor2=int(input("Ingrese segundo va
lor:"))
self.sumar()
self.restar()
self.multiplicar()
self.dividir()

def sumar(self):
suma=self.valor1+self.valor2
print("La suma es",suma)

def restar(self):
resta=self.valor1-self.valor2
print("La rersta es",resta)

def multiplicar(self):
multi=self.valor1*self.valor2
print("El producto es",multi)

def dividir(self):
divi=self.valor1/self.valor2
print("La division es",divi)
# bloque principal

operacion1=Operacion()
Nuestro método __init__ además de cargar los dos enteros procede a llamar a
los métodos que calculan la suma, resta, multiplicación y división de los dos
valores ingresados.
La llamada de los métodos de la misma clase se hace antecediendo al nombre
del método la palabra self:

def __init__(self):
self.valor1=int(input("Ingrese primer valor:"))
self.valor2=int(input("Ingrese segundo valor:"))
self.sumar()
self.restar()
self.multiplicar()
self.dividir()

El método que calcula la suma de los dos atributos cargados en el método


__init__ define una variable local llamada suma y guarda la suma de los dos
atributos. Posteriormente muestra la suma por pantalla:

def sumar(self):
suma=self.valor1+self.valor2
print("La suma es",suma)

De forma similar los otros métodos calculan la resta, multiplicación y división de


los dos valores ingresados:

def sumar(self):
suma=self.valor1+self.valor2
print("La suma es",suma)

def restar(self):
resta=self.valor1-self.valor2
print("La rersta es",resta)

def multiplicar(self):
multi=self.valor1*self.valor2
print("El producto es",multi)

def dividir(self):
divi=self.valor1/self.valor2
print("La division es",divi)

En el bloque principal de nuestro programa solo requerimos crear un objeto de


la clase Operación ya que el resto de los métodos se llama en el método
__init__:

# bloque principal

operacion1=Operacion()

Problema 2:
Plantear una clase que administre dos listas de 5 nombres de alumnos y sus
notas. Mostrar un menú de opciones que permita:
1- Cargar alumnos.
2- Listar alumnos.
3- Mostrar alumnos con notas mayores o iguales a 7.
4- Finalizar programa.
Programa: ejercicio195.py
Ver video

class Alumnos:

def __init__(self):
self.nombres=[]
self.notas=[]

def menu(self):
opcion=0
while opcion!=4:
print("1- Cargar alumnos")
print("2- Listar alumnos")
print("3- Listado de alumnos con nota
s mayores o iguales a 7")
print("4- Finalizar programa")
opcion=int(input("Ingrese su opcion:"
))
if opcion==1:
self.cargar()
elif opcion==2:
self.listar()
elif opcion==3:
self.notas_altas()

def cargar(self):
for x in range(5):
nom=input("Ingrese nombre del alumno:
")
self.nombres.append(nom)
no=int(input("Nota del alumno:"))
self.notas.append(no)

def listar(self):
print("Listado completo de alumnos")
for x in range(5):
print(self.nombres[x],self.notas[x])
print("_____________________")
def notas_altas(self):
print("Alumnos con notas superiores o igu
ales a 7")
for x in range(5):
if self.notas[x]>=7:
print(self.nombres[x],self.notas[
x])
print("_____________________")

# bloque principal

alumnos=Alumnos()
alumnos.menu()
Si ejecutamos el programa podemos ver como aparece un menú de opciones y
podemos seleccionar para cargar, listar etc.:
El bloque principal del programa es muy sencillo, solo creamos un objeto de la
clase Alumno y llamamos posteriormente al método menu:

# bloque principal
alumnos=Alumnos()
alumnos.menu()

Ahora analicemos la clase Alumno, en el método __init__ procedemos a crear


dos atributos de tipo lista donde se almacenarán los nombres de alumnos y sus
notas:

class Alumnos:

def __init__(self):
self.nombres=[]
self.notas=[]

El método menu muestra una serie de opciones y solicita al operador que elija
una de ellas, según cual de ellas selecciona procede a llamar al método
respectivo:

def menu(self):
opcion=0
while opcion!=4:
print("1- Cargar alumnos")
print("2- Listar alumnos")
print("3- Listado de alumnos con notas mayores o iguales a 7")
print("4- Finalizar programa")
opcion=int(input("Ingrese su opcion:"))
if opcion==1:
self.cargar()
elif opcion==2:
self.listar()
elif opcion==3:
self.notas_altas()

Algo que no utilizamos hasta ahora del lenguaje Python son una forma
simplificada de if anidados con la sentencia elif:

if opcion==1:
self.cargar()
elif opcion==2:
self.listar()
elif opcion==3:
self.notas_altas()

Nosotros hasta ahora lo resolvíamos y podemos sin problema seguir utilizando


la sintaxis::

if opcion==1:
self.cargar()
else:
if opcion==2:
self.listar()
else:
if opcion==3:
self.notas_altas()

Pero podemos comprobar que si hay muchos if anidados la nueva sintaxis es


más clara.
El método menu se repite el while mientras no se ingrese en la variable local
opcion el valor 4.
El método cargar se llama desde el método menu, en el mismo procedemos a
cargar las dos listas paralelas con los nombres de alumnos y sus notas:

def cargar(self):
for x in range(5):
nom=input("Ingrese nombre del alumno:")
self.nombres.append(nom)
no=int(input("Nota del alumno:"))
self.notas.append(no)

El método listar muestra las dos listas paralelas por completo e imprime una
línea separadora para que se vea in forma más clara:

def listar(self):
print("Listado completo de alumnos")
for x in range(5):
print(self.nombres[x],self.notas[x])
print("_____________________")

Finalmente el método notas_altas muestra solo los elementos de las listas


cuyas notas sean igual o superior a 7:

def notas_altas(self):
print("Alumnos con notas superiores o iguales a 7")
for x in range(5):
if self.notas[x]>=7:
print(self.nombres[x],self.notas[x])
print("_____________________")

Problema propuesto
• Confeccionar una clase que administre una agenda personal. Se debe
almacenar el nombre de la persona, teléfono y mail
Debe mostrar un menú con las siguientes opciones:
1- Carga de un contacto en la agenda.
2- Listado completo de la agenda.
3- Consulta ingresando el nombre de la persona.
4- Modificación de su teléfono y mail.
5- Finalizar programa.

Ver video
Solución

Retornar

46 - Colaboración de clases
Normalmente un problema resuelto con la metodología de programación
orientada a objetos no interviene una sola clase, sino que hay muchas clases
que interactúan y se comunican.
Plantearemos un problema separando las actividades en dos clases.

Problema 1:
Un banco tiene 3 clientes que pueden hacer depósitos y extracciones. También
el banco requiere que al final del día calcule la cantidad de dinero que hay
depositado.
Lo primero que hacemos es identificar las clases:
Podemos identificar la clase Cliente y la clase Banco.
Luego debemos definir los atributos y los métodos de cada clase:

Cliente
atributos
nombre
monto
métodos
__init__
depositar
extraer
retornar_monto

Banco
atributos
3 Cliente (3 objetos de la clase Cliente)
métodos
__init__
operar
depositos_totales

Programa: ejercicio197.py
Ver video

class Cliente:

def __init__(self,nombre):
self.nombre=nombre
self.monto=0
def depositar(self,monto):
self.monto=self.monto+monto

def extraer(self,monto):
self.monto=self.monto-monto

def retornar_monto(self):
return self.monto

def imprimir(self):
print(self.nombre,"tiene depositado la su
ma de",self.monto)

class Banco:

def __init__(self):
self.cliente1=Cliente("Juan")
self.cliente2=Cliente("Ana")
self.cliente3=Cliente("Diego")

def operar(self):
self.cliente1.depositar(100)
self.cliente2.depositar(150)
self.cliente3.depositar(200)
self.cliente3.extraer(150)
def depositos_totales(self):
total=self.cliente1.retornar_monto()+self
.cliente2.retornar_monto()+self.cliente3.retornar
_monto()
print("El total de dinero del banco es:",
total)
self.cliente1.imprimir()
self.cliente2.imprimir()
self.cliente3.imprimir()

# bloque principal

banco1=Banco()
banco1.operar()
banco1.depositos_totales()
Primero hacemos la declaración de la clase Cliente, en el método __init__
inicializamos los atributos nombre con el valor que llega como parámetro y el
atributo monto con el valor cero:

class Cliente:

def __init__(self,nombre):
self.nombre=nombre
self.monto=0

Recordemos que en Python para diferenciar un atributo de una variable local o


un parámetro le antecedemos la palabra clave self (es decir nombre es el
parámetro y self.nombre es el atributo):

self.nombre=nombre

El método que aumenta el atributo monto es:


def depositar(self,monto):
self.monto=self.monto+monto

Y el método que reduce el atributo monto del cliente es:

def extraer(self,monto):
self.monto=self.monto-monto

Lo más común para que otro objeto conozca el monto depositado por un
cliente es la implementación de un método que lo retorne:

def retornar_monto(self):
return self.monto

Para mostrar los datos del cliente tenemos el método:

def imprimir(self):
print(self.nombre,"tiene depositado la suma de",self.monto)

La segunda clase de nuestro problema es el Banco. Esta clase define tres


atributos de la clase Cliente (la clase Cliente colabora con la clase Banco):

class Banco:

def __init__(self):
self.cliente1=Cliente("Juan")
self.cliente2=Cliente("Ana")
self.cliente3=Cliente("Diego")

El método operar realiza una serie de depósitos y extracciones de los clientes:

def operar(self):
self.cliente1.depositar(100)
self.cliente2.depositar(150)
self.cliente3.depositar(200)
self.cliente3.extraer(150)

El método que muestra cuanto dinero tiene depositado el banco se resuelve


pidiendo a cada cliente que retorne el monto que tiene:
def depositos_totales(self):
total=self.cliente1.retornar_monto()+self.cliente2.retornar_monto()+self
.cliente3.retornar_monto()
print("El total de dinero del banco es:",total)
self.cliente1.imprimir()
self.cliente2.imprimir()
self.cliente3.imprimir()

En el bloque principal de nuestro programa en Python procedemos a crear un


objeto de la clase Banco y llamar a los dos métodos:

# bloque principal

banco1=Banco()
banco1.operar()
banco1.depositos_totales()

En el bloque principal no se requiere crear objetos de la clase Cliente, esto


debido que los clientes son atributos del Banco.

Problema 2:
Plantear un programa que permita jugar a los dados. Las reglas de juego son:
se tiran tres dados si los tres salen con el mismo valor mostrar un mensaje que
"gano", sino "perdió".
Lo primero que hacemos es identificar las clases:
Podemos identificar la clase Dado y la clase JuegoDeDados.
Luego los atributos y los métodos de cada clase:

Dado
atributos
valor
métodos
tirar
imprimir
retornar_valor
JuegoDeDados
atributos
3 Dado (3 objetos de la clase Dado)
métodos
__init__
jugar

Programa: ejercicio198.py
Ver video

import random

class Dado:

def tirar(self):
self.valor=random.randint(1,6)

def imprimir(self):
print("Valor del dado:",self.valor)

def retornar_valor(self):
return self.valor

class JuegoDeDados:

def __init__(self):
self.dado1=Dado()
self.dado2=Dado()
self.dado3=Dado()

def jugar(self):
self.dado1.tirar()
self.dado1.imprimir()
self.dado2.tirar()
self.dado2.imprimir()
self.dado3.tirar()
self.dado3.imprimir()
if self.dado1.retornar_valor()==self.dado
2.retornar_valor() and self.dado1.retornar_valor(
)==self.dado3.retornar_valor():
print("Gano")
else:
print("Perdio")

# bloque principal del programa

juego_dados=JuegoDeDados()
juego_dados.jugar()
Importamos el módulo "random" de la biblioteca estándar de Python ya que
requerimos utilizar la función randint:

import random

La clase Dado define un método tirar que almacena en el atributo valor un


número aleatorio comprendido entre 1 y 6:
class Dado:

def tirar(self):
self.valor=random.randint(1,6)

Los otros dos métodos de la clase Dado tienen por objetivo mostrar el valor del
dado y retornar dicho valor a otra clase que lo requiera:

def imprimir(self):
print("Valor del dado:",self.valor)

def retornar_valor(self):
return self.valor

La clase JuegoDeDados define tres atributos de la clase Dado, en el método


__init__ crea dichos objetos:

class JuegoDeDados:

def __init__(self):
self.dado1=Dado()
self.dado2=Dado()
self.dado3=Dado()

En el método jugar de la clase JuegoDeDados procedemos a pedir a cada


dado que se tire, imprima y verificamos si los tres valores son iguales:

def jugar(self):
self.dado1.tirar()
self.dado1.imprimir()
self.dado2.tirar()
self.dado2.imprimir()
self.dado3.tirar()
self.dado3.imprimir()
if self.dado1.retornar_valor()==self.dado2.retornar_valor() and self.dad
o1.retornar_valor()==self.dado3.retornar_valor():
print("Gano")
else:
print("Perdio")

En el bloque principal de nuestro programa creamos un objeto de la clase


JuegoDeDados:

# bloque principal del programa

juego_dados=JuegoDeDados()
juego_dados.jugar()

Acotación
Para cortar una línea en varias líneas en Python podemos encerrar entre
paréntesis la condición:

if (self.dado1.retornar_valor()==self.dado2.retornar_valor()
and self.dado1.retornar_valor()==self.dado3.retornar_valor()):

O agregar una barra al final:

if self.dado1.retornar_valor()==self.dado2.retornar_valor() and \
self.dado1.retornar_valor()==self.dado3.retornar_valor():

Si no utilizamos los paréntesis o la barra al final y tratamos de disponer el if en


dos líneas se produce un error sintáctico:
Problema propuesto
• Plantear una clase Club y otra clase Socio.
La clase Socio debe tener los siguientes atributos: nombre y la
antigüedad en el club (en años).
En el método __init__ de la clase Socio pedir la carga por teclado del
nombre y su antigüedad.
La clase Club debe tener como atributos 3 objetos de la clase Socio.
Definir una responsabilidad para imprimir el nombre del socio con mayor
antigüedad en el club.

Ver video
Solución

Retornar

47 - Herencia
Vimos en el concepto anterior que dos clases pueden estar relacionadas por la
colaboración. Ahora veremos otro tipo de relaciones entre clases que es la
Herencia.
La herencia significa que se pueden crear nuevas clases partiendo de clases
existentes, que tendrá todas los atributos y los métodos de su 'superclase' o
'clase padre' y además se le podrán añadir otros atributos y métodos propios.
clase padre
Clase de la que desciende o deriva una clase. Las clases hijas (descendientes)
heredan (incorporan) automáticamente los atributos y métodos de la la clase
padre.
Subclase
Clase descendiente de otra. Hereda automáticamente los atributos y métodos
de su superclase. Es una especialización de otra clase.
Admiten la definición de nuevos atributos y métodos para aumentar la
especialización de la clase.
Veamos algunos ejemplos teóricos de herencia:
1) Imaginemos la clase Vehículo. Qué clases podrían derivar de ella?

Vehiculo

Colectivo Moto Auto

FordK Renault Fluence

Siempre hacia abajo en la jerarquía hay una especialización (las subclases


añaden nuevos atributos y métodos.
2) Imaginemos la clase Software. Qué clases podrían derivar de ella?

Software

DeAplicacion DeBase

ProcesadorTexto PlanillaDeCalculo SistemaOperativ


o

Word WordPerfect Excel Lotus123 Linux Window


s
El primer tipo de relación que habíamos visto entre dos clases, es la de
colaboración. Recordemos que es cuando una clase contiene un objeto de otra
clase como atributo.
Cuando la relación entre dos clases es del tipo "...tiene un..." o "...es parte
de...", no debemos implementar herencia. Estamos frente a una relación de
colaboración de clases no de herencia.
Si tenemos una ClaseA y otra ClaseB y notamos que entre ellas existe una
relacion de tipo "... tiene un...", no debe implementarse herencia sino declarar
en la clase ClaseA un atributo de la clase ClaseB.
Por ejemplo: tenemos una clase Auto, una clase Rueda y una clase Volante.
Vemos que la relación entre ellas es: Auto "...tiene 4..." Rueda, Volante "...es
parte de..." Auto; pero la clase Auto no debe derivar de Rueda ni Volante de
Auto porque la relación no es de tipo-subtipo sino de colaboración. Debemos
declarar en la clase Auto 4 atributos de tipo Rueda y 1 de tipo Volante.
Luego si vemos que dos clase responden a la pregunta ClaseA "..es un.."
ClaseB es posible que haya una relación de herencia.
Por ejemplo:

Auto "es un" Vehiculo


Circulo "es una" Figura
Mouse "es un" DispositivoEntrada
Suma "es una" Operacion

Problema 1:
Plantear una clase Persona que contenga dos atributos: nombre y edad. Definir
como responsabilidades la carga por teclado y su impresión.
En el bloque principal del programa definir un objeto de la clase persona y
llamar a sus métodos.
Declarar una segunda clase llamada Empleado que herede de la clase
Persona y agregue un atributo sueldo y muestre si debe pagar impuestos
(sueldo superior a 3000)
También en el bloque principal del programa crear un objeto de la clase
Empleado.
Programa: ejercicio200.py
Ver video

class Persona:
def __init__(self):
self.nombre=input("Ingrese el nombre:")
self.edad=int(input("Ingrese la edad:"))

def imprimir(self):
print("Nombre:",self.nombre)
print("Edad:",self.edad)

class Empleado(Persona):

def __init__(self):
super().__init__()
self.sueldo=float(input("Ingrese el sueld
o:"))

def imprimir(self):
super().imprimir()
print("Sueldo:",self.sueldo)

def paga_impuestos(self):
if self.sueldo>3000:
print("El empleado debe pagar impuest
os")
else:
print("No paga impuestos")
# bloque principal

persona1=Persona()
persona1.imprimir()
print("____________________________")
empleado1=Empleado()
empleado1.imprimir()
empleado1.paga_impuestos()
La clase Persona no tiene ninguna sintaxis nueva, como vemos definimos sus
métodos __init__ e imprimir, y sus dos atributos nombre y edad:

class Persona:

def __init__(self):
self.nombre=input("Ingrese el nombre:")
self.edad=int(input("Ingrese la edad:"))

def imprimir(self):
print("Nombre:",self.nombre)
print("Edad:",self.edad)

En el bloque principal creamos un objeto de la clase Persona:

# bloque principal

persona1=Persona()
persona1.imprimir()

La herencia se presenta en la clase Empleado, en la declaración de la clase


indicamos entre paréntesis el nombre de la clase de la cual hereda:

class Empleado(Persona):
Con esta sintaxis indicamos que la clase Empleado hereda de la clase
Persona. Luego de esto podemos decir que la clase Empleado ya tiene dos
atributos heredados que son el nombre y la edad, también hereda las
funcionalidades __init__ e imprimir.
La clase Empleado define un nuevo atributo que es el sueldo y tres
funcionalidades __init__, imprimir y paga_impuestos.
En el método __init__ de la clase Empleado primero llamamos al método
__init__ de la clase padre y luego cargamos el sueldo:

def __init__(self):
super().__init__()
self.sueldo=float(input("Ingrese el sueldo:"))

Mediante la función super() podemos llamar al método __init__ de la clase


padre.
Lo mismo sucede con el método imprimir donde primero llamamos al imprimir
de la clase padre y luego mostramos el sueldo del empleado:

def imprimir(self):
super().imprimir()
print("Sueldo:",self.sueldo)

La tercer funcionalidad es:

def paga_impuestos(self):
if self.sueldo>3000:
print("El empleado debe pagar impuestos")
else:
print("No paga impuestos")

En el bloque principal de nuestro programa definimos un objeto de la clase


Empleado y llamamos a sus funcionalidades:

empleado1=Empleado()
empleado1.imprimir()
empleado1.paga_impuestos()

Problema 2:
Ahora plantearemos otro problema empleando herencia. Supongamos que
necesitamos implementar dos clases que llamaremos Suma y Resta. Cada
clase tiene como atributo valor1, valor2 y resultado. Los métodos a definir son
cargar1 (que inicializa el atributo valor1), carga2 (que inicializa el atributo
valor2), operar (que en el caso de la clase "Suma" suma los dos atributos y en
el caso de la clase "Resta" hace la diferencia entre valor1 y valor2), y otro
método mostrar_resultado.
Si analizamos ambas clases encontramos que muchos atributos y métodos son
idénticos. En estos casos es bueno definir una clase padre que agrupe dichos
atributos y responsabilidades comunes.
La relación de herencia que podemos disponer para este problema es:

Operacion

Suma Resta

Solamente el método operar es distinto para las clases Suma y Resta (esto
hace que no lo podamos disponer en la clase Operacion en principio), luego los
métodos cargar1, cargar2 y mostrar_resultado son idénticos a las dos clases,
esto hace que podamos disponerlos en la clase Operacion. Lo mismo los
atributos valor1, valor2 y resultado se definirán en la clase padre Operacion.
Programa: ejercicio201.py
Ver video

class Operacion:

def __init__(self):
self.valor1=0
self.valor2=0
self.resultado=0

def cargar1(self):
self.valor1=int(input("Ingrese primer val
or:"))
def cargar2(self):
self.valor2=int(input("Ingrese segundo va
lor:"))

def mostrar_resultado(self):
print(self.resultado)

def operar(self):
pass

class Suma(Operacion):

def operar(self):
self.resultado=self.valor1+self.valor2

class Resta(Operacion):

def operar(self):
self.resultado=self.valor1-self.valor2

# bloque princpipal

suma1=Suma()
suma1.cargar1()
suma1.cargar2()
suma1.operar()
print("La suma de los dos valores es")
suma1.mostrar_resultado()

resta1=Resta()
resta1.cargar1()
resta1.cargar2()
resta1.operar()
print("La resta de los valores es:")
resta1.mostrar_resultado()
En este problema la clase Operación tiene por objetivo agrupar atributos y
funcionalidades que se heredarán en otras clases.
La clase Operación inicializa en el metodo __init__ tres atributos:

class Operacion:

def __init__(self):
self.valor1=0
self.valor2=0
self.resultado=0

Define dos métodos para cargar los atributos valor1 y valor2:

def cargar1(self):
self.valor1=int(input("Ingrese primer valor:"))

def cargar2(self):
self.valor2=int(input("Ingrese segundo valor:"))

Definimos un método para imprimir el atributo resultado:

def mostrar_resultado(self):
print(self.resultado)

Como la clase Operación se trata de una clase genérica que busca agrupar
funcionalidades y atributos para otras clases podemos definir un método operar
pero no podemos implementar ninguna funcionalidad:

def operar(self):
pass

En Python para indicar que un método está vacío se utiliza la palabra clave
"pass".
En el bloque principal de nuestro programa no creamos objetos de la clase
Operación. La clase Operación tiene sentido que otras clases hereden de esta.
Tanto la clase Suma y Resta heredan de la clase Operación y reescriben el
método operar con la funcionalidad que le corresponde a cada clase:

class Suma(Operacion):

def operar(self):
self.resultado=self.valor1+self.valor2

class Resta(Operacion):

def operar(self):
self.resultado=self.valor1-self.valor2

Finalmente en el bloque principal de nuestro programa en Python creamos un


objeto de la clase Suma y otro de la clase Resta y llamamos a sus respectivos
métodos en un orden lógico:

# bloque princpipal

suma1=Suma()
suma1.cargar1()
suma1.cargar2()
suma1.operar()
print("La suma de los dos valores es")
suma1.mostrar_resultado()

resta1=Resta()
resta1.cargar1()
resta1.cargar2()
resta1.operar()
print("La resta de los valores es:")
resta1.mostrar_resultado()

Problema propuesto
• Declarar una clase Cuenta y dos subclases CajaAhorra y PlazoFijo.
Definir los atributos y métodos comunes entre una caja de ahorro y un
plazo fijo y agruparlos en la clase Cuenta.
Una caja de ahorro y un plazo fijo tienen un nombre de titular y un
monto. Un plazo fijo añade un plazo de imposición en días y una tasa de
interés. Hacer que la caja de ahorro no genera intereses.
En el bloque principal del programa definir un objeto de la clase
CajaAhorro y otro de la clase PlazoFijo.

Ver video
Solución

Retornar

48 - Variables de clase
Hemos visto como definimos atributos en una clase anteponiendo la palabra
clave self:

class Persona:

def __init__(self,nombre):
self.nombre=nombre
Los atributos son independientes por cada objeto o instancia de la clase, es
decir si definimos tres objetos de la clase Persona, todas las personas tienen
un atributo nombre pero cada uno tiene un valor independiente:

class Persona:

def __init__(self,nombre):
self.nombre=nombre

# bloque principal

persona1=Persona("Juan")
persona2=Persona("Ana")
persona3=Persona("Luis")

print(persona1.nombre) # Juan
print(persona2.nombre) # Ana
print(persona3.nombre) # Luis

En algunas situaciones necesitamos almacenar datos que sean compartidos


por todos los objetos de dicha clase, en esas situaciones debemos emplear
variables de clase.
Para definir una variable de clase lo hacemos dentro de la clase pero fuera de
sus métodos:

class Persona:

variable=20

def __init__(self,nombre):
self.nombre=nombre

# bloque principal
persona1=Persona("Juan")
persona2=Persona("Ana")
persona3=Persona("Luis")

print(persona1.nombre) # Juan
print(persona2.nombre) # Ana
print(persona3.nombre) # Luis

print(persona1.variable) # 20
Persona.variable=5
print(persona2.variable) # 5

Se reserva solo un espacio para la variable "variable", independientemente que


se definan muchos objetos de la clase Persona. La variable "variable" es
compartida por todos los objetos persona1,persona2 y persona3.
Para modificar la variable de clase hacemos referencia al nombre de la clase y
seguidamente el nombre de la variable:

Persona.variable=5

Problema 1:
Definir una clase Cliente que almacene un código de cliente y un nombre.
En la clase Cliente definir una variable de clase de tipo lista que almacene
todos los clientes que tienen suspendidas sus cuentas corrientes.
Imprimir por pantalla todos los datos de clientes y el estado que se encuentra
su cuenta corriente.
Programa: ejercicio203.py
Ver video

class Cliente:
suspendidos=[]

def __init__(self,codigo,nombre):
self.codigo=codigo
self.nombre=nombre

def imprimir(self):
print("Codigo:",self.codigo)
print("Nombre:",self.nombre)
self.esta_suspendido()

def esta_suspendido(self):
if self.codigo in Cliente.suspendidos:
print("Esta suspendido")
else:
print("No esta suspendido")
print("_____________________________")

def suspender(self):
Cliente.suspendidos.append(self.codigo)

# bloque principal

cliente1=Cliente(1,"Juan")
cliente2=Cliente(2,"Ana")
cliente3=Cliente(3,"Diego")
cliente4=Cliente(4,"Pedro")

cliente3.suspender()
cliente4.suspender()

cliente1.imprimir()
cliente2.imprimir()
cliente3.imprimir()
cliente4.imprimir()

print(Cliente.suspendidos)
La clase Cliente define una variable de clase llamada suspendidos que es de
tipo lista y por ser variable de clase es compartida por todos los objetos que
definamos de dicha clase:

class Cliente:
suspendidos=[]

En el método imprimir mostramos el código, nombre del cliente y si se


encuentra suspendida su cuenta corriente:

def imprimir(self):
print("Codigo:",self.codigo)
print("Nombre:",self.nombre)
self.esta_suspendido()

El método suspender lo que hace es agregar el código de dicho cliente a la


lista de clientes suspendidos:

def suspender(self):
Cliente.suspendidos.append(self.codigo)

El método que analiza si está suspendido el cliente verifica si su codigo se


encuentra almacenado en la variable de clase suspendidos:

def esta_suspendido(self):
if self.codigo in Cliente.suspendidos:
print("Esta suspendido")
else:
print("No esta suspendido")
print("_____________________________")

Para probar esta clase en el bloque principal creamos cuatro objetos de la


clase Cliente:

# bloque principal

cliente1=Cliente(1,"Juan")
cliente2=Cliente(2,"Ana")
cliente3=Cliente(3,"Diego")
cliente4=Cliente(4,"Pedro")

Suspendemos dos clientes:

cliente3.suspender()
cliente4.suspender()

Y luego imprimimos los datos de cada cliente:

cliente1.imprimir()
cliente2.imprimir()
cliente3.imprimir()
cliente4.imprimir()

Podemos imprimir la variable de clase suspendidos de la clase Cliente:

print(Cliente.suspendidos)

Es importante remarcar que todos los objetos acceden a una única lista
llamada suspendidos gracias a que se definió como variable de clase.

Problema propuesto
• Plantear una clase llamada Jugador.
Definir en la clase Jugador los atributos nombre y puntaje, y los métodos
__init__, imprimir y pasar_tiempo (que debe reducir en uno la variable de
clase).
Declarar dentro de la clase Jugador una variable de clase que indique
cuantos minutos falta para el fin de juego (iniciarla con el valor 30)
Definir en el bloque principal dos objetos de la clase Jugador.
Reducir dicha variable hasta llegar a cero.

Ver video
Solución

Retornar

49 - Método especial __str__


Podemos hacer que se ejecute un método definido por nosotros cuando
pasamos un objeto a la función print o cuando llamamos a la función str
(convertir a string)
¿Qué sucede cuando llamamos a la función print y le pasamos como
parámetro un objeto?
Ver video

class Persona:
def __init__(self,nom,ape):
self.nombre=nom
self.apellido=ape

persona1=Persona("Jose","Rodriguez")
print(persona1)

Nos muestra algo parecido a esto:

<__main__.Persona object at 0x03E99C90>

Python nos permite redefinir el método que se debe ejecutar. Esto se hace
definiendo en la clase el método especial __str__
En el ejemplo anterior si queremos que se muestre el nombre y apellido
separados por coma cuando llamemos a la función print el código que
debemos implementar es el siguiente:

class Persona:
def __init__(self,nom,ape):
self.nombre=nom
self.apellido=ape

def __str__(self):
cadena=self.nombre+","+self.apellido
return cadena

persona1=Persona("Jose","Rodriguez")
print(persona1)

Como vemos debemos implementar el método __str__ y retornar un string,


este luego será el que imprime la función print:

def __str__(self):
cadena=self.nombre+","+self.apellido
return cadena

Esta característica definida en Python nos permite crear programas muy


legibles y flexibles.
El método __str__ también se ejecuta si llamamos a la función str y pasamos
como parámetro un objeto que tiene definido dicho método:

class Persona:
def __init__(self,nom,ape):
self.nombre=nom
self.apellido=ape

def __str__(self):
cadena=self.nombre+","+self.apellido
return cadena

# bloque principal

persona1=Persona("Jose","Rodriguez")
persona2=Persona("Ana","Martinez")
print(str(persona1)+"-"+str(persona2)) # Jose,Rodriguez-Ana,Martinez

Problema 1:
Definir una clase llamada Punto con dos atributos x e y.
Crearle el método especial __str__ para retornar un string con el formato (x,y).
Programa: ejercicio205.py
Ver video

class Punto:

def __init__(self, x, y):


self.x=x
self.y=y

def __str__(self):
return "("+str(self.x)+","+str(self.y)+")
"

# bloque principal

punto1=Punto(10,3)
punto2=Punto(3,4)
print(punto1)
print(punto2)
La clase Punto define dos métodos especiales. El método __init__ donde
inicializamos los atributos x e y:

class Punto:
def __init__(self, x, y):
self.x=x
self.y=y

Y el segundo método especial que definimos es el __str__ que debe retornar


un string. Para generar el string debemos concatenar valores fijos como "(" y
convertir a string los atributos que son enteros mediante la función str:

def __str__(self):
return "("+str(self.x)+","+str(self.y)+")"

Luego en el bloque principal después de definir dos objetos de la clase Punto


procedemos a llamar a la función print y le pasamos cada uno de los objetos:

# bloque principal

punto1=Punto(10,3)
punto2=Punto(3,4)
print(punto1)
print(punto2)

Hay que tener en cuenta que cuando pasamos a la función print el objeto
punto1 en ese momento se llama el método especial __str__ que tiene por
objetivo retornar un string que nos haga más legible lo que representa dicho
objeto.

Problema 2:
Declarar una clase llamada Familia. Definir como atributos el nombre del padre,
madre y una lista con los nombres de los hijos.
Definir el método especial __str__ que retorne un string con el nombre del
padre, la madre y de todos sus hijos.
Programa: ejercicio206.py
Ver video

class Familia:

def __init__(self,padre,madre,hijos=[]):
self.padre=padre
self.madre=madre
self.hijos=hijos

def __str__(self):
cadena=self.padre+","+self.madre
for hi in self.hijos:
cadena=cadena+","+hi
return cadena

# bloque principal

familia1=Familia("Pablo","Ana",["Pepe","Julio"])
familia2=Familia("Jorge","Carla")
familia3=Familia("Luis","Maria",["marcos"])

print(familia1)
print(familia2)
print(familia3)
Para resolver este problema el método __init__ recibe en forma obligatoria el
nombre del padre, madre y en forma opcional una lista con los nombres de los
hijos:

class Familia:

def __init__(self,padre,madre,hijos=[]):
self.padre=padre
self.madre=madre
self.hijos=hijos

Si no tiene hijos la familia el atributo hijos almacena una lista vacía.


El método especial __str__ genera un string con los nombres del padre, madre
y todos los hijos:

def __str__(self):
cadena=self.padre+","+self.madre
for hi in self.hijos:
cadena=cadena+","+hi
return cadena

En el bloque principal creamos tres objetos de la clase Familia y pasamos al


método __init__ distintas composiciones de familias:

# bloque principal

familia1=Familia("Pablo","Ana",["Pepe","Julio"])
familia2=Familia("Jorge","Carla")
familia3=Familia("Luis","Maria",["marcos"])

print(familia1)
print(familia2)
print(familia3)
Problema propuesto
• Desarrollar un programa que implemente una clase llamada Jugador.
Definir como atributos su nombre y puntaje.
Codificar el método especial __str__ que retorne el nombre y si es
principiante (menos de 1000 puntos) o experto (1000 o más puntos)

Ver video
Solución

Retornar

50 - Redefinición de los operadores


matemáticos con objetos
Python nos permite redefinir los operadores matemáticos cuando planteamos
una clase.
Los métodos especiales que debemos implementar son los siguientes:
Para el operador +:

__add__(self,objeto2)

Para el operador -:

__sub__(self,objeto2)

Para el operador *:

__mul__(self,objeto2)

Para el operador //:

__floordiv__(self,objeto2)

Para el operador /:

__truediv__(self,objeto2)

Problema 1:
Veamos con un ejemplo la sintaxis para redefinir el operador +.
Crearemos una clase Cliente de un banco y redefiniremos el operador + para
que nos retorne la suma de los depósitos de los dos clientes que estamos
sumando.
Programa: ejercicio208.py
Ver video

class Cliente:

def __init__(self,nombre,monto):
self.nombre=nombre
self.monto=monto

def __add__(self,objeto2):
s=self.monto+objeto2.monto
return s

cli1=Cliente('Ana',1200)
cli2=Cliente('Luis',1500)
print("El total depositado por los dos clientes e
s")
print(cli1+cli2)

Definimos el método especial __add__ al que le llega como parámetro además


de self un objeto.
El objeto que llega corresponde al que se encuentra luego del operador +, es
decir clie2:

print(cli1+cli2)

El algoritmo del método queda codificado como sigue:

def __add__(self,objeto2):
s=self.monto+objeto2.monto
return s
Es muy importante tener en cuenta que debemos redefinir un operador
matemático siempre y cuando haga nuestro programa más legible.
Debemos redefinir los operadores +,-,*,/ etc. solo para las clases que con solo
leer su nombre el programador intuya que operación implementaría dicho
operador.

Problema 2:
Desarrollar una clase llamada Lista, que permita pasar al método __init__ una
lista de valores enteros.
Redefinir los operadores +,-,* y // con respecto a un valor entero.
Programa: ejercicio209.py
Ver video

class Lista:

def __init__(self, lista):


self.lista=lista

def imprimir(self):
print(self.lista)

def __add__(self,entero):
nueva=[]
for x in range(len(self.lista)):
nueva.append(self.lista[x]+entero)
return nueva

def __sub__(self,entero):
nueva=[]
for x in range(len(self.lista)):
nueva.append(self.lista[x]-entero)
return nueva

def __mul__(self,entero):
nueva=[]
for x in range(len(self.lista)):
nueva.append(self.lista[x]*entero)
return nueva

def __floordiv__(self,entero):
nueva=[]
for x in range(len(self.lista)):
nueva.append(self.lista[x]//entero)
return nueva

# bloque principal

lista1=Lista([3,4,5])
lista1.imprimir()
print(lista1+10)
print(lista1-10)
print(lista1*10)
print(lista1//10)
Al método __init__ llega la lista de enteros:

class Lista:
def __init__(self, lista):
self.lista=lista

Cuando sumamos a la lista un entero llega como parámetro el entero. Dentro


del método generamos una nueva lista y la retornamos:

def __add__(self,entero):
nueva=[]
for x in range(len(self.lista)):
nueva.append(self.lista[x]+entero)
return nueva

Retornar

51 - Redefinición de los operadores


relacionales con objetos
Python también nos permite redefinir los operadores relacionales cuando
planteamos una clase.
Los métodos especiales que podemos implementar son los siguientes:
Para el operador ==:

__eq__(self,objeto2)

Para el operador !=:

__ne__(self,objeto2)

Para el operador >:

__gt__(self,objeto2)

Para el operador >=:

__ge__(self,objeto2)
Para el operador <:

__lt__(self,objeto2)

Para el operador <=:

__le__(self,objeto2)

Es importante recordar que una redefinición de un operador tiene sentido si


ayuda y hace más claro nuestro algoritmo.

Problema 1:
Crear una clase Persona que tenga como atributo el nombre y la edad.
El operador == retornará verdadero si las dos personas tienen la misma edad,
el operador > retornará True si la edad del objeto de la izquierda tiene una
edad mayor a la edad del objeto de la derecha del operador >, y así
sucesivamente
Programa: ejercicio210.py
Ver video

class Persona:

def __init__(self,nombre, edad):


self.nombre=nombre
self.edad=edad

def __eq__(self,objeto2):
if self.edad==objeto2.edad:
return True
else:
return False

def __ne__(self,objeto2):
if self.edad!=objeto2.edad:
return True
else:
return False

def __gt__(self,objeto2):
if self.edad>objeto2.edad:
return True
else:
return False

def __ge__(self,objeto2):
if self.edad>=objeto2.edad:
return True
else:
return False

def __lt__(self,objeto2):
if self.edad<objeto2.edad:
return True
else:
return False

def __le__(self,objeto2):
if self.edad<=objeto2.edad:
return True
else:
return False

# bloque principal

persona1=Persona('juan',22)
persona2=Persona('ana',22)
if persona1==persona2:
print("Las dos personas tienen la misma edad.
")
else:
print("No tienen la misma edad.")
Como podemos observar planteamos un método por cada operador relacional:

def __eq__(self,objeto2):
if self.edad==objeto2.edad:
return True
else:
return False

El método recibe como referencia (self) que es la dirección del objeto ubicado a
la izquierda del operador relacionar y como parámetro (objeto2) la referencia
del objeto ubicado a la derecha del operador. Solo nos queda analizar el
atributo edad de cada objeto y retornar True si los dos almacenan el mismo
valor, en caso contrario retornamos False.

Problema 2:
Plantear una clase Rectangulo. Definir dos atributos (ladomenor y ladomayor).
Redefinir el operador == de tal forma que tengan en cuenta la superficie del
rectángulo. Lo mismo hacer con todos los otros operadores relacionales.
Programa: ejercicio211.py
Ver video
class Rectangulo:

def __init__(self,lmenor,lmayor):
self.lmenor=lmenor
self.lmayor=lmayor

def retornar_superficie(self):
return self.lmenor*self.lmayor

def __eq__(self,objeto2):
if self.retornar_superficie()==objeto2.re
tornar_superficie():
return True
else:
return False

def __ne__(self,objeto2):
if self.retornar_superficie()!=objeto2.re
tornar_superficie():
return True
else:
return False

def __gt__(self,objeto2):
if self.retornar_superficie()>objeto2.ret
ornar_superficie():
return True
else:
return False

def __ge__(self,objeto2):
if self.retornar_superficie()>=objeto2.re
tornar_superficie():
return True
else:
return False

def __lt__(self,objeto2):
if self.retornar_superficie()<objeto2.ret
ornar_superficie():
return True
else:
return False

def __le__(self,objeto2):
if self.retornar_superficie()<=objeto2.re
tornar_superficie():
return True
else:
return False

# bloque principal
rectangulo1=Rectangulo(10,10)
rectangulo2=Rectangulo(5,20)
if rectangulo1==rectangulo2:
print("Los rectangulos tienen la misma superf
icie")
else:
print("Los rectangulos no tienen la misma sup
erficie")
Similar al concepto anterior redefinimos los métodos especiales e
implementamos un algoritmo para verificar las superficies de dos objetos
rectángulos (llamamos al método retornar_superficie de cada objeto):

def __eq__(self,objeto2):
if self.retornar_superficie()==objeto2.retornar_superficie():
return True
else:
return False

Retornar

52 - Editores para programar en


Python
Hasta ahora hemos aprendido los conceptos fundamentales de Python y
hemos utilizado el entorno de desarrollo IDLE que se instala por defecto con
Python.
Cuando necesitamos una herramienta más completa para trabajar en forma
más intensiva con Python el entorno IDLE nos puede quedar limitado.
Veremos ahora otros editores que facilitan la programación en Python y
elegiremos uno de ellos para continuar estudiando Python:
1. PyCharm: Es un entorno de desarrollo creado por la empresa Jet Brains.
Viene en dos versiones, la básica que es open source y la podemos
descargar del sitio de: JetBrains
En la misma página tenemos el enlace para registrarnos y comprar la
versión profesional.
2. PyDev IDE: Este entorno de desarrollo es una adaptación del editor
Eclipse. Lo podemos descargar del sitio de: pydev
Es open source al igual que el editor Eclipse.
3. Wing: Es un entorno para trabajar con Python con numerosas
herramientas para programar y depurar programas. Hay una versión
gratuita, pero la que tiene todas las herramientas es comercial. Podemos
descargar este entorno del sitio: wingware
4. VS Code: Es un editor de texto que agregando extensiones podemos
trabajar con Python con herramientas para programar y depurar
programas. Es creado y mantenido por la empresa Microsoft. Es open
source y multiplataforma (Windows, Linux y Mac)
En el último año se esta convirtiendo en el editor de texto más utilizado por
los programadores profesionales de todo el mundo.
Podemos comprobar esta situación si visitamos la encuesta de
desarrolladores 2019 del sitio de stackoverflow
Otro dato que nos puede hacer dimensionar el empleo de Visual Studio
Code para programar con Python es la cantidad de descargas de la
extensión:
Por lo expuesto anteriormente en el próximo concepto descargaremos el editor
VS Code y de ahora en más empezaremos a utilizarlo este editor para ver los
temas de Python que nos faltan estudiar.

Retornar

53 - Instalación del editor Visual


Studio Code (VSCode) y de la
extensión para Python
Descarga e instalación del VS Code.
Ver video
El editor de texto VSCode ha sido creado y es mantenido por Microsoft. Lo
distribuye con licencia Open Source y por lo tanto en forma gratuita. Lo
debemos descargar del sitio code.visualstudio.com, como podemos comprobar
está disponible tanto para Windows, Mac y Linux:
Una vez descargado procedemos a instalarlo siguiendo los pasos del asistente:
Ya tenemos instalado y funcionando VSCode:
El tema o aspecto visual por defecto es el oscuro, pero para que se vea más
fácil en este tutorial lo cambiaremos por un aspecto más claro.
Para cambiar el tema presionamos el botón del engranaje en la parte inferior
izquierda y seleccionamos "Tema de color":

Yo seleccionaré el tema "Light + (default light)":


Podemos cerrar la pestaña de bienvenida y tendremos el editor VSCode en su
mínima expresión:
El resultado sin pestañas abiertas es:
Como vemos en el fondo del editor aparecen los 5 comandos más comunes
que tenemos que hacer normalmente cuando trabajamos con el editor de texto
VSCode como puede ser "Abrir archivo" con el atajo de teclas Ctrl + O.

Descarga de la extensión de Python para el editor VS


Code.
Una de las opciones fundamentales del editor de texto VSCode es la
posibilidad de agregar características mediante las "extensiones".
Existen miles de "extensiones" con objetivos tan diversos como:

• Lenguajes de programación (en nuestro caso Python)

• Depuradores

• Formateadores de código fuente


• Temas

• Teclas de acceso rápido de otros editores

Para consultar la tienda de extensiones para VSCode podemos


visitar marketplace.visualstudio.com/vscode.
La popularidad de las extensiones la podemos comprobar cuando vemos la
cantidad de descargas de las mismas (la extensión de Python tiene más de 57
millones de descargas):

Instalación de una "Extensión"


Procederemos a instalar la extensión de Python en VSCode. Desde la "Barra
de actividades" a través del ícono:
Cuando seleccionamos una extensión se nos muestra una pestaña con toda la
información de dicha extensión:
Procederemos a su instalación presionando el botón "instalar" que aparece
dentro de la pestaña de la extensión, una vez instalada aparece un nuevo
botón para que se recargue el VSCode y comience a funcionar la extensión:

Ya tenemos todo listo para probar nuestro primer programa en Python


utilizando el editor VS Code, procedemos a crear un archivo 'ejercicio212.py' y
codificar:
Programa: ejercicio211.py

lado=input("Ingrese la medida del lado del cuadra


do:")
lado=int(lado)
superficie=lado*lado
print("La superficie del cuadrado es")
print(superficie)
Podemos ahora abrir la opción de depurar y proceder a ejecutar nuestra
aplicación en Python:
Acotaciones
Hemos visto en forma resumida los pasos para la instalación del editor VS
Code y de la extensión para trabajar con Python. Le sugiero que luego se tome
su tiempo para conocer en forma más profunda el editor VS Code mediante el
tutorial VS Code Ya

Retornar

54 - Depuración de programas en
VSCode
La depuración de programas es el proceso de identificar y corregir errores de
programación. VSCode nos trae dentro del editor y junto a extensiones este
proceso.
Dentro de la "Barra de actividades" de VSCode podemos identificar el ícono
que nos abre el diálogo de depuración:

Cada ambiente de trabajo tiene sus propias herramientas de depuración:


Node.JS, Python, C# etc.

Prueba de depuración con Python


Abriremos algún programa que hemos desarrollado para ver como podemos
depurarlo.
Programa: ejercicio069.js

lista=[10,7,3,7,2]
suma=0
x=0
while x<len(lista):
suma=suma+lista[x]
x=x+1
print("Los elementos de la lista son")
print(lista)
print("La suma de todos sus elementos es")
print(suma)
Podemos ejecutar la aplicación desde la consola y comprobaremos su
resultado:

Dispondremos un punto de ruptura cuando se sale del while. Esto se logra


disponiendo la flecha del mouse a la izquierda del comando y luego haciendo
clic:
Procederemos ahora a abrir la opción de "Depurar" ( Ctrl + Shift + D o el ícono
de la barra de actividades) e iniciamos la depuración.
El programa empieza a ejecutarse y se detiene en la línea donde dispusimos el
punto de ruptura (break point):
Como vemos aparece una barra de botones que nos permite:

• Continuar (F5) (el triángulo verde)

• Depurar paso a paso por procedimiento (F10)

• Depurar paso a paso por instrucciones (F11)

• Salir de depuración (Shift + F11)

• Reiniciar (Ctrl + Shift + F5)

• Detener (Shift+F5)

Disponiendo la flecha del mouse sobre el nombre de una variable (por ejemplo
'suma') se nos muestra su contenido:
Con esta mecánica podemos identificar errores lógicos que tenga nuestro
algoritmo.

Retornar

55 - pip : instalador de paquetes


Ver video
pip es un programa que viene con Python y nos permite instalar paquetes de
terceros con el objetivo de valernos de librerías de código desarrolladas por la
comunidad de Python.
El sitio que podemos visitar para conocer que paquetes están disponibles se
llama pypi.org . En este momento hay más de 191000 paquetes disponibles
sobre temas tan diversos como:
Como podemos ver existen paquetes en Python que nos pueden facilitar el
desarrollo de programas en una diversidad de temas muy amplio.
Para poder descargar un paquete del repositorio pypi.org debemos conocer
solo el nombre del paquete.

Instalación de un paquete
Para conocer los pasos en la instalación de un paquete almacenado en pypi
elegiremos el paquete 'wxPython' (tengamos en cuenta que es uno solo entre
más de 191000 disponibles) que tiene por objetivo facilitar la implementación
de interfaces visuales en Python.
Desde la línea de comandos debemos ejecutar:

pip install wxPython

Si estamos utilizando el editor VSCode podemos hacer esta actividad desde el


mismo editor escribiendo:
Después de esto ya podemos implementar aplicaciones en Python que hagan
uso del paquete wxPython.
Codificaremos un programa mínimo que muestre una ventana con el mensaje
"Hola Mundo" empleando el paquete wxPython:
Programa: ejercicio213.py

import wx

aplicacion = wx.App()
ventana = wx.Frame(parent=None,title="Hola Mundo"
)
ventana.Show()
aplicacion.MainLoop()
Si lo ejecutamos al programa podemos comprobar que nuestra aplicación no
se ejecuta en la consola del sistema operativo sino que aparece una interfaz
visual:
Siempre que utilizamos paquetes desarrollados por la comunidad debemos
visitar su documentación para poder utilizarlos en nuestros proyectos, por
ejemplo la documentación del paquete wxPython se encuentra aquí

Problema:
Mostrar una ventana con un botón en su interior. Al ser presionado mostrar un
mensaje.
El programa en Python haciendo uso del paquete wxPython requiere el
siguiente algoritmo:
Programa: ejercicio214.py

import wx

class Ventana(wx.Frame):

def __init__(self, *args, **kw):


super(Ventana, self).__init__(*args, **kw
)
self.boton1 =wx.Button(self, label="Presi
onar")
self.Bind(wx.EVT_BUTTON, self.presion_bot
on,self.boton1)

def presion_boton(self,evento):
wx.MessageBox("Hola mundo")

aplicacion = wx.App()
frm = Ventana(None, title='Prueba')
frm.Show()
aplicacion.MainLoop()
La ejecución de este programa nos muestra una ventana con un botón en su
interior:
Si se presiona el botón se muestra la ventana con el mensaje:
Conclusión
El objetivo de este concepto es aprender a instalar un paquete y su posterior
uso y no aprender las particularidades de la librería wxPython que instalamos.
Si quiere aprender todas las funcionalidades de wxPython visite el
sitio wxpython.org, en los próximos conceptos veremos otra librería de Python
para trabajar con GUI.

Retornar

56 - pip : funcionalidades
La aplicación pip es la herramienta fundamental que trae Python para la
instalación de paquetes para poder utilizarlos en nuestros proyectos.
• Vimos en el concepto anterior la sintaxis que se requiere para instalar un
paquete que se encuentra publicado en el sitio pypi.org:

• pip install [nombre del paquete]

• La actividad inversa de instalar un paquete en nuestro equipo se hace


indicando el comando 'uninstall', por ejemplo si queremos desintalar el
paquete 'wxPython' que instalamos en el concepto anterior lo hacemos
con la siguiente sintaxis:

• pip uninstall wxPython


Debemos ingresar la letra 'y' para confirmar la eliminación del paquete.
• Si queremos conocer todos los archivos que tiene un paquete que
hayamos instalado lo hacemos mediante la sintaxis:

• pip show --files wxPython

Esto nos muestra una lista completa de archivos que contiene el


paquete:
Hay una sintaxis resumida para la misma actividad:

pip show -f wxPython

• Para conocer todos los paquetes instalados en nuestro entorno de


Python debemos utilizar el comando 'list':

• pip list
Como podemos ver en el listado de paquetes además del paquete que
instalamos en el concepto anterior hay otros que vienen por defecto
cuando instalamos Python.
Los desarrolladores de paquetes para Python están constantemente
actualizando sus funcionalidades y sacan nuevas versiones. Si
queremos saber si alguno de nuestros paquetes está desactualizado
podemos ejecutar el comando list pasando el parámetro --outdated (se
nos muestran todos los paquetes desactualizados):

pip list --outdated

Si por alguna razón queremos instalar una versión más vieja de un


paquete debemos indicar en el comando 'install' la versión del mismo:

pip install wxPython==4.0.2

Indicamos el número exacto de versión a instalar.


Para actualizar un paquete ya instalado debemos pasar el parámetro
'upgrade':

pip install --upgrade wxPython

Para profundizar y tener todas las actualizaciones del programa 'pip' debemos
visitar la guía de referencia oficial.

Retornar

57 - Interfaz gráfica de usuario :


tkinter
La interfaz gráfica de usuario, conocida también como GUI (graphical user
interface) son fundamentales cuando queremos implementar programas para
usuarios finales que faciliten la entrada y salida de datos.
Vimos en el concepto anterior que Python puede hacer uso de la GUI
wxPython mediante la instalación del paquete respectivo. Python por defecto
instala el módulo 'tkinter' para la implementación de interfaces visuales. El
editor IDLE que viene con Python está desarrollado utilizando este módulo.
Veremos en una serie de conceptos como implementar interfaces visuales con
ventanas, botones, checkbox, label etc. haciendo uso del módulo 'tkinter'.
Lo primero que hay que tener en cuenta es que el módulo 'tkinter' (tk interface)
viene instalado por defecto con Python.

Problema:
Mostrar una ventana y que en su título aparezca el mensaje 'Hola Mundo'.
El programa en Python haciendo uso del módulo 'tkinter' requiere el siguiente
algoritmo:
Programa: ejercicio215.py
Ver video

import tkinter as tk

ventana1=tk.Tk()
ventana1.title("Hola Mundo")
ventana1.mainloop()
Lo primero que hacemos es importar el módulo tkinter y le definimos un alias
luego de la palabra clave as. Es más fácil luego escribir 'tk' en lugar de 'tkinter':

import tkinter as tk

La librería tkinter está codificada con la metodología de programación


orientada a objetos. El módulo 'tkinter' tiene una clase llamada 'Tk' que
representa una ventana. Debemos crear un objeto de dicha clase:

ventana1=tk.Tk()

Seguidamente llamamos al método 'title' y le pasamos un string con el mensaje


que queremos que aparezca en la barra del título de la ventana:

ventana1.title("Hola Mundo")

Para que se muestre la ventana en el monitor debemos llamar por último al


método 'mainloop' que pertenece a la clase Tk:

ventana1.mainloop()

Hemos codificado el programa más pequeño utilizando el módulo 'tkinter':


Acotaciones
Si utilizamos el editor VSCode en lugar del editor IDLE podemos tener grandes
ventajas cuando codificamos el programa. Por ejemplo luego de escribir el
nombre del objeto podemos ver que gracias a 'IntelliSense' se nos muestran
todos sus métodos y una descripción del mismo:
Aplicación orientada a objetos
Todos los ejemplos que haremos de ahora en más independientemente de su
complejidad utilizaremos la metodología de POO (Programación Orientada a
Objetos)
El programa anterior modificado con POO queda:
Programa: ejercicio215.py

import tkinter as tk

class Aplicacion:
def __init__(self):
self.ventana1=tk.Tk()
self.ventana1.title("Hola Mundo")
self.ventana1.mainloop()
aplicacion1=Aplicacion()
Planteamos una clase llamada 'Aplicacion' y en su método '__init__' creamos el
objeto de la clase 'Tk' para que se muestre la ventana.
Debemos crear luego un objeto de la clase 'Aplicacion':

aplicacion1=Aplicacion()

Retornar

58 - tkinter : controles Button y Label


En las interfaces visuales las ventanas son controles visuales contenedores de
otros controles como los botones y etiquetas de texto.
Veremos los pasos que debemos dar si queremos que se muestren objetos de
la clase Button y Label en nuestras ventanas.

Problema:
Mostrar una ventana y en su interior dos botones y una label. La label muestra
inicialmente el valor 1. Cada uno de los botones permiten incrementar o
decrementar en uno el contenido de la label
Programa: ejercicio216.py
Ver video

import tkinter as tk

class Aplicacion:
def __init__(self):
self.valor=1
self.ventana1=tk.Tk()
self.ventana1.title("Controles Button y L
abel")
self.label1=tk.Label(self.ventana1, text=
self.valor)
self.label1.grid(column=0, row=0)
self.label1.configure(foreground="red")

self.boton1=tk.Button(self.ventana1, text
="Incrementar", command=self.incrementar)
self.boton1.grid(column=0, row=1)

self.boton2=tk.Button(self.ventana1, text
="Decrementar", command=self.decrementar)
self.boton2.grid(column=0, row=2)

self.ventana1.mainloop()

def incrementar(self):
self.valor=self.valor+1
self.label1.config(text=self.valor)

def decrementar(self):
self.valor=self.valor-1
self.label1.config(text=self.valor)
aplicacion1=Aplicacion()
Definimos un atributo en la clase Aplicacion y almacenamos el valor 1:

self.valor=1

Creamos la ventana y le fijamos un título como hemos visto en el concepto


anterior:

self.ventana1=tk.Tk()
self.ventana1.title("Controles Button y Label")

Ahora creamos un objeto de la clase Label y le pasamos como primer


parámetro la referencia a la ventana donde debe aparecer la label y el
parámetro text con el valor inicial de la Label:

self.label1=tk.Label(self.ventana1, text=self.valor)

Para ubicar los controles visuales en la ventana veremos más adelante que
hay diferentes Layout, por ahora en forma muy sencilla mediante la llamada al
método grid indicaremos en los parámetros column y row la ubicación del
mismo:

self.label1.grid(column=0, row=0)

Para que el texto de la Label se muestre de color rojo llamamos al método


configure y le pasamos en el parámetro foreground el string "red":

self.label1.configure(foreground="red")

La creación de los dos botones es similar a la creación de la label, en el primer


parámetro indicamos la referencia de la ventana donde se debe mostrar el
botón, en el parámetro text indicamos el texto a mostrar dentro del botón y
finalmente en el parámetro command pasamos la referencia del método que se
ejecutará cuando el operador lo presione:

self.boton1=tk.Button(self.ventana1, text="Incrementar", command=self.in


crementar)
self.boton1.grid(column=0, row=1)

self.boton2=tk.Button(self.ventana1, text="Decrementar", command=self.de


crementar)
self.boton2.grid(column=0, row=2)
Para que los botones se encuentren abajo de la Label al llamar al método grid
pasamos en el parámetro row los valores 1 y 2. Como todos los controles se
encuentran en la misma columna pasamos en column el valor 0.
No olvidar a llamar al final del método __init__ al método mainloop():

self.ventana1.mainloop()

El método incrementar se ejecuta cuando el operador presiona el boton1


(dentro del mismo incrementamos en uno el atributo valor y actualizamos el
contenido de la label1 llamando al método config y en el parámetro text el
nuevo valor a mostrar):

def incrementar(self):
self.valor=self.valor+1
self.label1.config(text=self.valor)

El algoritmo del método decrementar solo difiere en que decrementa en uno el


atributo valor:

def decrementar(self):
self.valor=self.valor-1
self.label1.config(text=self.valor)

No olvidemos crear un objeto de la clase 'Aplicacion' en el bloque principal del


programa:

aplicacion1=Aplicacion()

Cuando ejecutamos la aplicación tenemos una interfaz visual similar a esta:


Acotaciones
La sintaxis para modificar la propiedad 'text' de la label1 se puede hacer
llamando al método config como lo hemos hecho:

self.label1.config(text=self.valor)

O mediante la sintaxis:

self.label1["text"]=self.valor

Problema:
Mostrar dos Label, en una se muestra el nombre del programa y en la segunda
el año de creación. Disponer un botón para finalizar el programa.
No permitir al usuario redimensionar la ventana.
Programa: ejercicio217.py
Ver video

import tkinter as tk
import sys

class Aplicacion:
def __init__(self):
self.ventana1=tk.Tk()
self.ventana1.title("Prueba")
self.label1=tk.Label(self.ventana1, text=
"Sistema de facturación")
self.label1.grid(column=0, row=0)
self.label2=tk.Label(self.ventana1, text=
"2018")
self.label2.grid(column=0, row=1)
self.boton1=tk.Button(self.ventana1, text
="Finalizar", command=self.finalizar)
self.boton1.grid(column=0, row=2)
self.ventana1.resizable(False, False)
self.ventana1.mainloop()

def finalizar(self):
sys.exit(0)

aplicacion1=Aplicacion()
En esta aplicación para no permitir redimensionar ni el ancho ni el alto del la
ventana debemos llamar al método resizable y pasar el valor False a cada
parámetro.
Cuando queremos finalizar un programa en Python debemos llamar a la
función exit que se encuentra en el módulo sys, por ello hemos importado
dicho módulo al principio:

import sys

Cuando ejecutamos la aplicación tenemos una interfaz visual similar a esta:

Problemas propuestos
• Disponer dos objetos de la clase Button con las etiquetas: "varón" y
"mujer", al presionarse mostrar en la barra de títulos de la ventana la
etiqueta del botón presionado.

Ver video

• Mostrar los botones del 1 al 5. Cuando se presiona mostrar en una Label


todos los botones presionados hasta ese momento.
Ver video
Solución

Retornar

59 - tkinter : control Entry


Hemos visto hasta ahora los controles Button y Label, ahora veremos otro
control visual indispensable para hacer la entrada de datos por teclado.
En tkinter el control de entrada de datos por teclado se llama Entry. Con este
control aparece el típico recuadro que cuando se le da foco aparece el cursor
en forma intermitente esperando que el operador escriba algo por teclado.

Problema:
Confeccionar una aplicación que permita ingresar un entero por teclado y al
presionar un botón muestre dicho valor elevado al cuadrado en una Label.
Programa: ejercicio220.py
Ver video

import tkinter as tk

class Aplicacion:
def __init__(self):
self.ventana1=tk.Tk()
self.label1=tk.Label(self.ventana1,text="
Ingrese un número:")
self.label1.grid(column=0, row=0)
self.dato=tk.StringVar()
self.entry1=tk.Entry(self.ventana1, width
=10, textvariable=self.dato)
self.entry1.grid(column=0, row=1)
self.boton1=tk.Button(self.ventana1, text
="Calcular Cuadrado", command=self.calcularcuadra
do)
self.boton1.grid(column=0, row=2)
self.label2=tk.Label(self.ventana1,text="
resultado")
self.label2.grid(column=0, row=3)
self.ventana1.mainloop()

def calcularcuadrado(self):
valor=int(self.dato.get())
cuadrado=valor*valor
self.label2.configure(text=cuadrado)

aplicacion1=Aplicacion()
La ejecución de esta aplicación muestra una interfaz visual similar a esta:
Veamos lo nuevo que aparece para definir un objeto de la clase Entry:

self.dato=tk.StringVar()
self.entry1=tk.Entry(self.ventana1, widt=10, textvariable=self.dato)
self.entry1.grid(column=0, row=1)

Cuando trabajamos con la clase Entry debemos también crear un objeto de la


clase StringVar y pasar dicho objeto al parámetro textvariable cuando se crea
el objeto de la clase Entry.
La clase StringVar al igual que la clase Entry están declaradas en el módulo
tkinter.
Cuando debemos rescatar el dato ingresado por el operador en el control de la
clase Entry en realidad lo hacemos del objeto de la clase StringVar mediante el
método get:

def calcularcuadrado(self):
valor=int(self.dato.get())
cuadrado=valor*valor
self.label2.configure(text=cuadrado)

Problema:
Confeccionar un programa que permita ingresar el nombre de usuario en un
control Entry y cuando se presione un botón mostrar el valor ingresado en la
barra de títulos de la ventana.
Programa: ejercicio221.py
Ver video

import tkinter as tk

class Aplicacion:
def __init__(self):
self.ventana1=tk.Tk()
self.label1=tk.Label(self.ventana1,text="
Ingrese nombre de usuario:")
self.label1.grid(column=0, row=0)
self.dato=tk.StringVar()
self.entry1=tk.Entry(self.ventana1, width
=20, textvariable=self.dato)
self.entry1.grid(column=1, row=0)
self.boton1=tk.Button(self.ventana1, text
="Ingresar", command=self.ingresar)
self.boton1.grid(column=1, row=1)
self.ventana1.mainloop()

def ingresar(self):
self.ventana1.title(self.dato.get())

aplicacion1=Aplicacion()
La ejecución de esta aplicación muestra una interfaz visual similar a esta:
Para que el botón aparezca debajo del control Entry debemos fijar el parámetro
'column' con el valor 1:

self.boton1.grid(column=1, row=1)

Debemos pensar nuestra pantalla como una cuadrícula donde definimos la fila
y columna para cada control:

self.label1.grid(column=0, row=0)
self.entry1.grid(column=1, row=0)
self.boton1.grid(column=1, row=1)

Debajo de la Label no aparece nada, eso debido a que no hemos dispuesto un


control en dicha posición.
Cuando se presiona el botón extraemos del objeto de la clase StringVar el dato
ingresado por el operador en el control Entry:

def ingresar(self):
self.ventana1.title(self.dato.get())

Problemas propuestos
• Confeccionar un programa que permita ingresar dos números en
controles de tipo Entry, luego sumar los dos valores ingresados y
mostrar la suma en una Label al presionar un botón.
Ver video

• Ingresar el nombre de usuario y clave en controles de tipo Entry. Si se


ingresa las cadena (usuario: juan, clave="abc123") luego mostrar en el
título de la ventana el mensaje "Correcto" en caso contrario mostrar el
mensaje "Incorrecto".
Para mostrar '*' cuando se ingresa la clave debemos pasar en el
parámetro 'show' el caracter a mostrar:

• self.entry2=tk.Entry(self.ventana1, width=30, textvariable=self.d


ato2, show="*")

Ver video
Solución

Retornar

60 - tkinter : control Radiobutton


Otro control visual muy común es el Radiobutton que normalmente se
muestran un conjunto de Radiobutton y permiten la selección de solo uno de
ellos. Se los debe agrupar para que actúen en conjunto, es decir cuando se
selecciona uno automáticamente se deben deseleccionar los otros.

Problema:
Mostrar dos controles de tipo Radiobutton con las etiquetas "Varón" y "Mujer",
cuando se presione un botón actualizar una Label con el Radiobutton
seleccionado.
Programa: ejercicio224.py
Ver video

import tkinter as tk

class Aplicacion:
def __init__(self):
self.ventana1=tk.Tk()
self.seleccion=tk.IntVar()
self.seleccion.set(2)
self.radio1=tk.Radiobutton(self.ventana1,
text="Varon", variable=self.seleccion, value=1)
self.radio1.grid(column=0, row=0)
self.radio2=tk.Radiobutton(self.ventana1,
text="Mujer", variable=self.seleccion, value=2)
self.radio2.grid(column=0, row=1)
self.boton1=tk.Button(self.ventana1, text
="Mostrar seleccionado", command=self.mostrarsele
ccionado)
self.boton1.grid(column=0, row=2)
self.label1=tk.Label(self.ventana1,text="
opcion seleccionada")
self.label1.grid(column=0, row=3)
self.ventana1.mainloop()

def mostrarseleccionado(self):
if self.seleccion.get()==1:
self.label1.configure(text="opcion se
leccionada=Varon")
if self.seleccion.get()==2:
self.label1.configure(text="opcion se
leccionada=Mujer")

aplicacion1=Aplicacion()
La ejecución de esta aplicación muestra una interfaz visual similar a esta:
Definimos dos objetos de la clase Radiobutton e iniciamos el parámetro
variable con la referencia de un objeto de la clase IntVar:

self.radio1=tk.Radiobutton(self.ventana1,text="Varon", variable=self.sel
eccion, value=1)
self.radio1.grid(column=0, row=0)
self.radio2=tk.Radiobutton(self.ventana1,text="Mujer", variable=self.sel
eccion, value=2)
self.radio2.grid(column=0, row=1)

Previamente hemos definido el objeto de la clase IntVar que se encuentra en el


módulo tk:

self.seleccion=tk.IntVar()
self.seleccion.set(2)

Aparece seleccionado por defecto el Radiobutton con la etiqueta "Mujer" ya


que mediante el método set fijamos el valor 2.
Cuando se presiona el botón analizamos el valor almacenado en el objeto
IntVar:

def mostrarseleccionado(self):
if self.seleccion.get()==1:
self.label1.configure(text="opcion seleccionada=Varon")
if self.seleccion.get()==2:
self.label1.configure(text="opcion seleccionada=Mujer")

Problema:
Disponer dos controles de tipo Entry para el ingreso de enteros. Mediante dos
controles Radiobutton permitir seleccionar si queremos sumarlos o restarlos. Al
presionar un botón mostrar el resultado de la operación seleccionada.
Programa: ejercicio225.py
Ver video

import tkinter as tk

class Aplicacion:
def __init__(self):
self.ventana1=tk.Tk()
self.label1=tk.Label(self.ventana1,text="
Ingrese primer valor:")
self.label1.grid(column=0, row=0)
self.dato1=tk.StringVar()
self.entry1=tk.Entry(self.ventana1, width
=20, textvariable=self.dato1)
self.entry1.grid(column=1, row=0)
self.label2=tk.Label(self.ventana1,text="
Ingrese segundo valor:")
self.label2.grid(column=0, row=1)
self.dato2=tk.StringVar()
self.entry2=tk.Entry(self.ventana1, width
=20, textvariable=self.dato2)
self.entry2.grid(column=1, row=1)
self.seleccion=tk.IntVar()
self.radio1=tk.Radiobutton(self.ventana1,
text="Sumar", variable=self.seleccion, value=1)
self.radio1.grid(column=1, row=2)
self.radio2=tk.Radiobutton(self.ventana1,
text="Restar", variable=self.seleccion, value=2)
self.radio2.grid(column=1, row=3)
self.boton1=tk.Button(self.ventana1, text
="Operar", command=self.operar)
self.boton1.grid(column=1, row=4)
self.label3=tk.Label(self.ventana1,text="
resultado")
self.label3.grid(column=1, row=5)
self.ventana1.mainloop()

def operar(self):
if self.seleccion.get()==1:
suma=int(self.dato1.get())+int(self.d
ato2.get())
self.label3.configure(text=suma)
if self.seleccion.get()==2:
resta=int(self.dato1.get())-int(self.
dato2.get())
self.label3.configure(text=resta)

aplicacion1=Aplicacion()
La ejecución de esta aplicación muestra una interfaz visual similar a esta:
Cuando se presiona el botón se dispara el método 'operar':

self.boton1=tk.Button(self.ventana1, text="Operar", command=self.operar)

En el método operar rescatamos de los objeto StringVar los valores ingresados


en los controles Entry:

def operar(self):
if self.seleccion.get()==1:
suma=int(self.dato1.get())+int(self.dato2.get())
self.label3.configure(text=suma)
if self.seleccion.get()==2:
resta=int(self.dato1.get())-int(self.dato2.get())
self.label3.configure(text=resta)

Problema propuesto
• Disponer tres controles de tipo Radiobutton con las etiquetas 'Rojo',
'Verde' y 'Azul'. Cuando se presione un botón cambiar el color de fondo
del formulario.
Si consideramos que la variable ventana1 es un objeto de la clase Tk,
luego si queremos que el fondo sea de color rojo debemos llamar al
método configure y en el parámetro bg indicar un string con el color a
activar ("red", "green" o "blue"):

• self.ventana1.configure(bg="red")

Ver video
Solución

Retornar

61 - tkinter : control Checkbutton


El control visual Checkbutton permite implementar un botón de dos estados,
más conocido como un cuadro de selección.

Problema:
Mostrar una ventana y en su interior tres controles de tipo Checkbutton cuyas
etiquetas correspondan a distintos lenguajes de programación. Cuando se
presione un botón mostrar en una Label la cantidad de Checkbutton que se
encuentran chequeados.
Programa: ejercicio227.py
Ver video

import tkinter as tk

class Aplicacion:
def __init__(self):
self.ventana1=tk.Tk()
self.seleccion1=tk.IntVar()
self.check1=tk.Checkbutton(self.ventana1,
text="Python", variable=self.seleccion1)
self.check1.grid(column=0, row=0)
self.seleccion2=tk.IntVar()
self.check2=tk.Checkbutton(self.ventana1,
text="C++", variable=self.seleccion2)
self.check2.grid(column=0, row=1)
self.seleccion3=tk.IntVar()
self.check3=tk.Checkbutton(self.ventana1,
text="Java", variable=self.seleccion3)
self.check3.grid(column=0, row=2)
self.boton1=tk.Button(self.ventana1, text
="Verificar", command=self.verificar)
self.boton1.grid(column=0, row=4)
self.label1=tk.Label(self.ventana1,text="
cantidad:")
self.label1.grid(column=0, row=5)
self.ventana1.mainloop()

def verificar(self):
cant=0
if self.seleccion1.get()==1:
cant+=1
if self.seleccion2.get()==1:
cant+=1
if self.seleccion3.get()==1:
cant+=1
self.label1.configure(text="cantidad:"+st
r(cant))

aplicacion1=Aplicacion()
La ejecución de esta aplicación muestra una interfaz visual similar a esta:
A cada control de tipo Checkbutton lo asociamos con un objeto de la clase
IntVar (por defecto el objeto de la clase IntVar almacena un cero indicando que
el Checkbutton debe aparecer no seleccionado):

self.seleccion1=tk.IntVar()
self.check1=tk.Checkbutton(self.ventana1,text="Python", variable=self.se
leccion1)
self.check1.grid(column=0, row=0)

Cuando se presiona el botón se ejecuta el método 'verificar' donde analizamos


que almacenan los objetos seleccion1, seleccion2 y seleccion3. En el caso de
almacenar un 1 significa que el Checkbutton asociado está seleccionado:

def verificar(self):
cant=0
if self.seleccion1.get()==1:
cant+=1
if self.seleccion2.get()==1:
cant+=1
if self.seleccion3.get()==1:
cant+=1
self.label1.configure(text="cantidad:"+str(cant))

Problema:
Disponer un control Checkbutton que muestre el siguiente mensaje: ¿Está de
acuerdo con los términos y condiciones?, además agregar un Button desactivo.
Cuando se tilde el Checkbutton inmediatamente activar el botón.
Programa: ejercicio228.py
Ver video

import tkinter as tk

class Aplicacion:
def __init__(self):
self.ventana1=tk.Tk()
self.seleccion=tk.IntVar()
self.check1=tk.Checkbutton(self.ventana1,
text="¿Está de acuerdo con los términos y condici
ones?", variable=self.seleccion, command=self.cam
biarestado)
self.check1.grid(column=0, row=0)
self.boton1=tk.Button(self.ventana1, text
="Entrar", state="disabled", command=self.ingresa
r)
self.boton1.grid(column=0, row=1)
self.ventana1.mainloop()

def cambiarestado(self):
if self.seleccion.get()==1:
self.boton1.configure(state="normal")
if self.seleccion.get()==0:
self.boton1.configure(state="disabled
")

def ingresar(self):
self.ventana1.title("Ingresando...")

aplicacion1=Aplicacion()
La ejecución de esta aplicación muestra una interfaz visual similar a esta:

Inmediatamente se inicia la aplicación el botón aparece desactivo (es decir el


operador no lo puede presionar) debido a que hemos inicializado el parámetro
state con el valor "disabled":

self.boton1=tk.Button(self.ventana1, text="Entrar", state="disabled", co


mmand=self.ingresar)

Otro concepto importante de este ejemplo es que podemos asociar un evento a


un control de tipo Checkbutton mediante el parámetro "command" (el mismo se
ejecuta cada vez que hacemos un cambio en el control):

self.check1=tk.Checkbutton(self.ventana1,text="¿Está de acuerdo con los


términos y condiciones?", variable=self.seleccion, command=self.cambiarestado)

El método "cambiarestado" tiene por objetivo activar o desactivar el botón


según el estado del Checkbutton:

def cambiarestado(self):
if self.seleccion.get()==1:
self.boton1.configure(state="normal")
if self.seleccion.get()==0:
self.boton1.configure(state="disabled")
Problema propuesto
• Disponer varios objetos de la clase Checkbutton con nombres de
navegadores web. En el título de la ventana mostrar todos los nombres
de navegadores seleccionados.

Ver video
Solución

Retornar
62 - tkinter : control Listbox
El control visual Listbox se emplea para mostrar una lista de items. El usuario
puede seleccionar uno o más elementos de la lista según como se lo configure
al crearlo.

Problema:
Disponer un Listbox con una serie de nombres de frutas. Permitir la selección
solo de uno de ellos. Cuando se presione un botón recuperar la fruta
seleccionada y mostrarla en una Label.
Programa: ejercicio230.py
Ver video

import tkinter as tk

class Aplicacion:
def __init__(self):
self.ventana1=tk.Tk()
self.listbox1=tk.Listbox(self.ventana1)
self.listbox1.grid(column=0,row=0)
self.listbox1.insert(0,"papa")
self.listbox1.insert(1,"manzana")
self.listbox1.insert(2,"pera")
self.listbox1.insert(3,"sandia")
self.listbox1.insert(4,"naranja")
self.listbox1.insert(5,"melon")
self.boton1=tk.Button(self.ventana1, text=
"Recuperar", command=self.recuperar)
self.boton1.grid(column=0, row=1)
self.label1=tk.Label(self.ventana1,text="S
eleccionado:")
self.label1.grid(column=0, row=2)
self.ventana1.mainloop()

def recuperar(self):
if len(self.listbox1.curselection())!=0:
self.label1.configure(text=self.listbo
x1.get(self.listbox1.curselection()[0]))

aplicacion1=Aplicacion()
La ejecución de esta aplicación muestra una interfaz visual similar a esta:

Creamos un objeto de la clase Listbox, por defecto solo se puede seleccionar


un único elemento:
self.listbox1=tk.Listbox(self.ventana1)

Insertamos una serie de items en el Listbox mediante el método insert


(indicamos en el primer parámetro la posición y en el segundo el valor a
insertar):

self.listbox1.insert(0,"papa")
self.listbox1.insert(1,"manzana")
self.listbox1.insert(2,"pera")
self.listbox1.insert(3,"sandia")
self.listbox1.insert(4,"naranja")
self.listbox1.insert(5,"melon")

Cuando se presiona el botón de recuperar mediante el método get


recuperamos un item de la posición seleccionada:

def recuperar(self):
if len(self.listbox1.curselection())!=0:
self.label1.configure(text=self.listbox1.get(self.listbox1.curselect
ion()[0]))

El método curselection retorna una tupla con todas las posiciones


seleccionadas del Listbox. Como se trata de un Listbox que permite la
selección de un único item luego por eso accedemos al item de la tupla de la
posición 0.

Problema:
Disponer un Listbox con una serie de nombres de frutas. Permitir la selección
de varias frutas. Cuando se presione un botón recuperar todas las frutas
seleccionadas y mostrarlas en una Label.
Programa: ejercicio231.py
Ver video

import tkinter as tk

class Aplicacion:
def __init__(self):
self.ventana1=tk.Tk()
self.listbox1=tk.Listbox(self.ventana1, se
lectmode=tk.MULTIPLE)
self.listbox1.grid(column=0,row=0)
self.listbox1.insert(0,"papa")
self.listbox1.insert(1,"manzana")
self.listbox1.insert(2,"pera")
self.listbox1.insert(3,"sandia")
self.listbox1.insert(4,"naranja")
self.listbox1.insert(5,"melon")
self.boton1=tk.Button(self.ventana1, text=
"Recuperar", command=self.recuperar)
self.boton1.grid(column=0, row=1)
self.label1=tk.Label(self.ventana1,text="S
eleccionado:")
self.label1.grid(column=0, row=2)
self.ventana1.mainloop()

def recuperar(self):
if len(self.listbox1.curselection())!=0:
todas=''
for posicion in self.listbox1.curselec
tion():
todas+=self.listbox1.get(posicion)
+"\n"
self.label1.configure(text=todas)

aplicacion1=Aplicacion()
La ejecución de esta aplicación muestra una interfaz visual similar a esta:

Cuando creamos el Listbox iniciamos el parámetro selectmode con el valor


almacenado en la variable MULTIPLE del módulo tkinter:

self.listbox1=tk.Listbox(self.ventana1, selectmode=tk.MULTIPLE)

Para mostrar todas las frutas seleccionadas ahora debemos disponer un for
para recorrer la tupla que retorna el método curselection y concatenarlas:

def recuperar(self):
if len(self.listbox1.curselection())!=0:
todas=''
for posicion in self.listbox1.curselection():
todas+=self.listbox1.get(posicion)+"\n"
self.label1.configure(text=todas)

Barra de scroll
Por defecto no aparece una barra de scroll si la cantidad de item supera el
tamaño del cuadro del Listbox. Para que se muestre una barra de scroll la
debemos crear y enlazar con el Listbox.
El mismo programa anterior pero con la barra de scroll queda:
Programa: ejercicio232.py
Ver video
import tkinter as tk

class Aplicacion:
def __init__(self):
self.ventana1=tk.Tk()
self.scroll1 = tk.Scrollbar(self.ventana1,
orient=tk.VERTICAL)
self.listbox1=tk.Listbox(self.ventana1, se
lectmode=tk.MULTIPLE, yscrollcommand=self.scroll1.
set)
self.listbox1.grid(column=0,row=0)
self.scroll1.configure(command=self.listbo
x1.yview)
self.scroll1.grid(column=1, row=0, sticky=
'NS')
self.listbox1.insert(0,"papa")
self.listbox1.insert(1,"manzana")
self.listbox1.insert(2,"pera")
self.listbox1.insert(3,"sandia")
self.listbox1.insert(4,"naranja")
self.listbox1.insert(5,"melon")
self.listbox1.insert(6,"limon")
self.listbox1.insert(7,"kiwi")
self.listbox1.insert(5,"banana")
self.listbox1.insert(5,"uva")
self.listbox1.insert(5,"papaya")
self.listbox1.insert(5,"mandarina")
self.listbox1.insert(5,"frutilla")
self.boton1=tk.Button(self.ventana1, text=
"Recuperar", command=self.recuperar)
self.boton1.grid(column=0, row=1)
self.label1=tk.Label(self.ventana1,text="S
eleccionado:")
self.label1.grid(column=0, row=2)
self.ventana1.mainloop()

def recuperar(self):
if len(self.listbox1.curselection())!=0:
todas=''
for posicion in self.listbox1.curselec
tion():
todas+=self.listbox1.get(posicion)
+"\n"
self.label1.configure(text=todas)

aplicacion1=Aplicacion()
Creamos un objeto de la clase Scrollbar que se encuentra declarado en el
módulo tkinter:

self.scroll1 = tk.Scrollbar(self.ventana1, orient=tk.VERTICAL)

Al crear el Listbox pasamos en el parámetro yscrollcommand la referencia del


método set del Scrollbar creado:

self.listbox1=tk.Listbox(self.ventana1, selectmode=tk.MULTIPLE, yscrollc


ommand=self.scroll1.set)

Al Scrollbar configuramos el parámetro command con la referencia del método


yview del Listbox:

self.scroll1.configure(command=self.listbox1.yview)
Finalmente ubicamos el Scrollbar en la segunda columna y hacemos que se
expanda de 'N' North a 'S' South configurando sticky:

self.scroll1.grid(column=1, row=0, sticky='NS')

La ejecución de esta aplicación muestra una interfaz visual similar a esta:

Problema propuesto
• Solicitar el ingreso del nombre de una persona y seleccionar de un
control Listbox un país. Al presionar un botón mostrar en la barra de la
ventana el nombre ingresado y el país seleccionado.

Ver video
Solución

Retornar

63 - módulo ttk
Tk hemos dicho que es una biblioteca de controles visuales que los podemos
acceder desde Python y desde otros lenguajes de programación.
En la versión Tk 8.5 sumó una nueva serie de controles visuales ( Notebook,
Combobox etc.) y modernizó los que hemos visto en los conceptos anteriores.
Para hacer uso de esta nueva versión de la biblioteca en Python se
implementó un nuevo módulo y se lo agregó al paquete tkinter.
Para hacer uso de este conjunto de Widget (controles visuales) debemos
importar el paquete ttk.
Todo lo que conocemos hasta ahora de los controles visuales del módulo
tkinter funciona prácticamente sin cambios, lo que deberemos hacer es crear
objetos de la clase Button, Entry etc. recuperándolos ahora del módulo
tkinter.ttk

Importar el módulo ttk


Debemos utilizar la siguiente sintaxis para importar el nuevo módulo:

from tkinter import ttk

Veamos algunos de los ejemplos ya resueltos pero haciendo uso de los Widget
de este nuevo módulo.

Problema:
Mostrar una ventana y en su interior dos botones y una label utilizando el
módulo ttk. La label muestra inicialmente el valor 1. Cada uno de los botones
permiten incrementar o decrementar en uno el contenido de la label
Programa: ejercicio234.py
Ver video

import tkinter as tk
from tkinter import ttk

class Aplicacion:
def __init__(self):
self.valor=1
self.ventana1=tk.Tk()
self.ventana1.title("Controles Button y L
abel")
self.label1=ttk.Label(self.ventana1, text
=self.valor)
self.label1.grid(column=0, row=0)
self.label1.configure(foreground="red")

self.boton1=ttk.Button(self.ventana1, tex
t="Incrementar", command=self.incrementar)
self.boton1.grid(column=0, row=1)

self.boton2=ttk.Button(self.ventana1, tex
t="Decrementar", command=self.decrementar)
self.boton2.grid(column=0, row=2)

self.ventana1.mainloop()

def incrementar(self):
self.valor=self.valor+1
self.label1.config(text=self.valor)

def decrementar(self):
self.valor=self.valor-1
self.label1.config(text=self.valor)

aplicacion1=Aplicacion()
Como los tres controles (Label y Button) son de este nuevo módulo podemos
ver que su representación visual es distinta:
Recordemos como se veían utilizando el módulo tkinter:

Si bien los cambios visuales que aparecen en la clase Button no son


significativos el módulo tkinter.ttk trae nuevas funcionalidades, nuevos
controles y permite que nuestra interfaz visual se adapte al sistema operativo
donde se está ejecutando (Windows, Mac, Linux etc.)
Analicemos que cambios debemos disponer a nuestra aplicación para utilizar
las componentes Button y Label del módulo tkinter.ttk.
Debemos seguir importando el paquete tkinter como lo veníamos haciendo:

import tkinter as tk

Se sigue utilizando la clase 'Tk' para crear la ventana principal:

self.ventana1=tk.Tk()

El primer cambio es la necesidad de importar el módulo ttk que se encuentra


en el paquete tkinter:

from tkinter import ttk

El segundo y último cambio es que cada vez que debemos crear un control
visual lo referenciamos del nuevo módulo ttk:

self.label1=ttk.Label(self.ventana1, text=self.valor)
...
self.boton1=ttk.Button(self.ventana1, text="Incrementar", command=self.i
ncrementar)
...
self.boton2=ttk.Button(self.ventana1, text="Decrementar", command=self.d
ecrementar)

Recordemos que antes creábamos los controles haciendo referencia al módulo


tkinter mediante el alias tk:

self.label1=tk.Label(self.ventana1, text=self.valor)

Resolvamos otros problemas ya resueltos empleando el nuevo módulo de


Widged propuesto en el módulo tkinter.ttk.

Problema:
Ingresar el nombre de usuario y clave en controles de tipo Entry. Si se ingresa
las cadena (usuario: juan, clave="abc123") luego mostrar en el título de la
ventana el mensaje "Correcto" en caso contrario mostrar el mensaje
"Incorrecto". Utilizar Widget del módulo ttk.
Programa: ejercicio235.py
Ver video

import tkinter as tk
from tkinter import ttk

class Aplicacion:
def __init__(self):
self.ventana1=tk.Tk()
self.label1=ttk.Label(text="Ingrese nombr
e de usuario:")
self.label1.grid(column=0, row=0)
self.dato1=tk.StringVar()
self.entry1=ttk.Entry(self.ventana1, widt
h=30, textvariable=self.dato1)
self.entry1.grid(column=1, row=0)
self.label2=ttk.Label(text="Ingrese clave
:")
self.label2.grid(column=0, row=1)
self.dato2=tk.StringVar()
self.entry2=ttk.Entry(self.ventana1, widt
h=30, textvariable=self.dato2, show="*")
self.entry2.grid(column=1, row=1)
self.boton1=ttk.Button(self.ventana1, tex
t="Ingresar", command=self.ingresar)
self.boton1.grid(column=1, row=2)
self.ventana1.mainloop()

def ingresar(self):
if self.dato1.get()=="juan" and self.dato
2.get()=="abc123":
self.ventana1.title("Correcto")
else:
self.ventana1.title("Incorrecto")

aplicacion1=Aplicacion()
La interfaz visual queda:

Nuevamente los únicos cambios que hemos implementado es la importación


del módulo ttk:

from tkinter import ttk


Y la creación de los 5 Widget:

self.label1=ttk.Label(text="Ingrese nombre de usuario:")


self.entry1=ttk.Entry(self.ventana1, width=30, textvariable=self.dato1)
self.label2=ttk.Label(text="Ingrese clave:")
self.entry2=ttk.Entry(self.ventana1, width=30, textvariable=self.dato2,
show="*")
self.boton1=ttk.Button(self.ventana1, text="Ingresar", command=self.ingr
esar)

Es importante notar que los objetos de la clase StringVar pertenecen al


paquete tkinter y no al nuevo paquete ttk:

self.dato1=tk.StringVar()

Problema:
Mostrar dos controles de tipo Radiobutton con las etiquetas "Varón" y "Mujer",
cuando se presione un botón actualizar una Label con el Radiobutton
seleccionado.
Programa: ejercicio236.py
Ver video

import tkinter as tk
from tkinter import ttk

class Aplicacion:
def __init__(self):
self.ventana1=tk.Tk()
self.seleccion=tk.IntVar()
self.seleccion.set(2)
self.radio1=ttk.Radiobutton(self.ventana1
,text="Varon", variable=self.seleccion, value=1)
self.radio1.grid(column=0, row=0)
self.radio2=ttk.Radiobutton(self.ventana1
,text="Mujer", variable=self.seleccion, value=2)
self.radio2.grid(column=0, row=1)
self.boton1=ttk.Button(self.ventana1, tex
t="Mostrar seleccionado", command=self.mostrarsel
eccionado)
self.boton1.grid(column=0, row=2)
self.label1=ttk.Label(text="opcion selecc
ionada")
self.label1.grid(column=0, row=3)
self.ventana1.mainloop()

def mostrarseleccionado(self):
if self.seleccion.get()==1:
self.label1.configure(text="opcion se
leccionada=Varon")
if self.seleccion.get()==2:
self.label1.configure(text="opcion se
leccionada=Mujer")

aplicacion1=Aplicacion()
La interfaz visual con el módulo ttk queda:
Problema:
Mostrar una ventana y en su interior tres controles de tipo Checkbutton cuyas
etiquetas correspondan a distintos lenguajes de programación. Cuando se
presione un botón mostrar en una Label la cantidad de Checkbutton que se
encuentran chequeados. Utilizar Widget del módulo ttk.
Programa: ejercicio237.py
Ver video

import tkinter as tk
from tkinter import ttk

class Aplicacion:
def __init__(self):
self.ventana1=tk.Tk()
self.seleccion1=tk.IntVar()
self.check1=ttk.Checkbutton(self.ventana1
,text="Python", variable=self.seleccion1)
self.check1.grid(column=0, row=0)
self.seleccion2=tk.IntVar()
self.check2=ttk.Checkbutton(self.ventana1
,text="C++", variable=self.seleccion2)
self.check2.grid(column=0, row=1)
self.seleccion3=tk.IntVar()
self.check3=ttk.Checkbutton(self.ventana1
,text="Java", variable=self.seleccion3)
self.check3.grid(column=0, row=2)
self.boton1=ttk.Button(self.ventana1, tex
t="Verificar", command=self.verificar)
self.boton1.grid(column=0, row=4)
self.label1=ttk.Label(text="cantidad:")
self.label1.grid(column=0, row=5)
self.ventana1.mainloop()

def verificar(self):
cant=0
if self.seleccion1.get()==1:
cant+=1
if self.seleccion2.get()==1:
cant+=1
if self.seleccion3.get()==1:
cant+=1
self.label1.configure(text="cantidad:"+st
r(cant))

aplicacion1=Aplicacion()
La interfaz visual con el módulo ttk queda:

Acotaciones
El módulo ttk no implementa el Widget Listbox, pero podemos mezclar en una
aplicación controles visuales de los dos paquetes.
Problema:
Disponer un Listbox con una serie de nombres de frutas. Permitir la selección
solo de uno de ellos. Cuando se presione un botón recuperar la fruta
seleccionada y mostrarla en una Label.
Programa: ejercicio238.py
Ver video

import tkinter as tk
from tkinter import ttk

class Aplicacion:
def __init__(self):
self.ventana1=tk.Tk()
self.listbox1=tk.Listbox(self.ventana1)
self.listbox1.grid(column=0,row=0)
self.listbox1.insert(0,"papa")
self.listbox1.insert(1,"manzana")
self.listbox1.insert(2,"pera")
self.listbox1.insert(3,"sandia")
self.listbox1.insert(4,"naranja")
self.listbox1.insert(5,"melon")
self.boton1=ttk.Button(self.ventana1, tex
t="Recuperar", command=self.recuperar)
self.boton1.grid(column=0, row=1)
self.label1=ttk.Label(text="Seleccionado:
")
self.label1.grid(column=0, row=2)
self.ventana1.mainloop()
def recuperar(self):
if len(self.listbox1.curselection())!=0:
self.label1.configure(text=self.listb
ox1.get(self.listbox1.curselection()[0]))

aplicacion1=Aplicacion()
Notemos que la clase Listbox la recuperamos del módulo tkinter a través de su
alias tk:

self.listbox1=tk.Listbox(self.ventana1)

Si tratamos de recuperarla del otro módulo se nos informará que no existe


mediante un mensaje de error:

Retornar

64 - ttk : control Combobox


El control Combobox del paquete ttk permite seleccionar un string de un
conjunto de items que se despliegan.
Podemos indicar cual elemento muestre por defecto mediante el método
'current'.
Por defecto el operador puede además de seleccionar un elemento cargar por
teclado cualquier cadena.

Problema:
Mostrar en una ventana un control de tipo Combobox con los días de la
semana. Cuando se presione un botón actualizar una Label con el día
seleccionado.
Programa: ejercicio239.py
Ver video

import tkinter as tk
from tkinter import ttk

class Aplicacion:
def __init__(self):
self.ventana1=tk.Tk()
self.label1=ttk.Label(self.ventana1, text
="Seleccione un día de la semana")
self.label1.grid(column=0, row=0)
self.opcion=tk.StringVar()
diassemana=("lunes","martes","miércoles",
"jueves","viernes","sábado","domingo")
self.combobox1=ttk.Combobox(self.ventana1
,
width=10,
textvariable=se
lf.opcion,
values=diassema
na)
self.combobox1.current(0)
self.combobox1.grid(column=0, row=1)
self.boton1=tk.Button(self.ventana1, text
="Recuperar", command=self.recuperar)
self.boton1.grid(column=0, row=2)
self.label2=ttk.Label(self.ventana1, text
="Día seleccionado:")
self.label2.grid(column=0, row=3)
self.ventana1.mainloop()

def recuperar(self):
self.label2.configure(text=self.opcion.ge
t())

aplicacion1=Aplicacion()
La ejecución de esta aplicación muestra una interfaz visual similar a esta:

Para crear un Combobox debemos hacer referencia al módulo ttk:

self.opcion=tk.StringVar()
diassemana=("lunes","martes","miércoles","jueves","viernes","sábado","do
mingo")
self.combobox1=ttk.Combobox(self.ventana1,
width=10,
textvariable=self.opcion,
values=diassemana)
self.combobox1.current(0)
self.combobox1.grid(column=0, row=1)

Debemos pasar en el parámetro values una tupla con los elementos que debe
mostrar el control Combobox. Asociamos al parámetro textvariable un objeto de
la clase StringVar para poder posteriormente recuperar el valor seleccionado.
Mediante el método current podemos indicar cual de los elementos debe
aparecer seleccionado.
Si ejecutamos la aplicación y escribimos dentro del Combobox podemos ver
que nos deja ingresar cualquier string. Para desactivar la edición del
Combobox debemos iniciar el parámetro state con el valor 'readonly':

self.combobox1=ttk.Combobox(self.ventana1,
width=10,
textvariable=self.opcion,
values=diassemana,
state='readonly')

Problema propuesto
• Solicitar el ingreso del nombre de una persona y seleccionar de un
control Combobox un país. Al presionar un botón mostrar en la barra de
la ventana el nombre ingresado y el país seleccionado.

Ver video
Solución

Retornar

65 - tkinter : control Menu


Para implementar los típicos menú de barra horizontales que aparecen en las
aplicaciones cuando utilizamos la librería Tk necesitamos crear objetos de la
clase Menu que se encuentra declarada en el paquete tkinter y no en el
paquete tkinter.ttk.
Veremos con un ejemplo implementar un menú con una serie de opciones.

Problema:
Confeccionar una aplicación que muestre dos opciones en el menú de barra
superior. La primer opción despliega un submenú que permita cambiar el color
de fondo del formulario y la segunda permita cambiar el tamaño de formulario:

Programa: ejercicio241.py
Ver video

import tkinter as tk

class Aplicacion:
def __init__(self):
self.ventana1=tk.Tk()
menubar1 = tk.Menu(self.ventana1)
self.ventana1.config(menu=menubar1)
opciones1 = tk.Menu(menubar1)
opciones1.add_command(label="Rojo", comma
nd=self.fijarrojo)
opciones1.add_command(label="Verde", comm
and=self.fijarverde)
opciones1.add_command(label="Azul", comma
nd=self.fijarazul)
menubar1.add_cascade(label="Colores", men
u=opciones1)
opciones2 = tk.Menu(menubar1)
opciones2.add_command(label="640x480", co
mmand=self.ventanachica)
opciones2.add_command(label="1024x800", c
ommand=self.ventanagrande)
menubar1.add_cascade(label="Tamaños", men
u=opciones2)
self.ventana1.mainloop()

def fijarrojo(self):
self.ventana1.configure(background="red")

def fijarverde(self):
self.ventana1.configure(background="green
")

def fijarazul(self):
self.ventana1.configure(background="blue"
)

def ventanachica(self):
self.ventana1.geometry("640x480")

def ventanagrande(self):
self.ventana1.geometry("1024x800")
aplicacion1=Aplicacion()
Importamos solo el módulo tkinter ya que no utilizamos controles del módulo
tkinter.ttk:

import tkinter as tk

Luego de crear el objeto de la clase Tk procedemos a crear un objeto de la


clase Menu y pasar como referencia la ventana:

self.ventana1=tk.Tk()
menubar1 = tk.Menu(self.ventana1)

Pasamos al parámetro menu de la ventana el objeto de la clase Menu que


acabamos de crear (si no hacemos esto no aparecerá luego el menú de
opciones:

self.ventana1.config(menu=menubar1)

Creamos un segundo objeto de la clase Menu, pero en este caso le pasamos


la referencia del primer objeto de la clase Menu que creamos, también
añadimos las tres opciones que mostrará:

opciones1 = tk.Menu(menubar1)
opciones1.add_command(label="Rojo", command=self.fijarrojo)
opciones1.add_command(label="Verde", command=self.fijarverde)
opciones1.add_command(label="Azul", command=self.fijarazul)

Finalmente llamamos al método 'add_cascade' del menubar1 que creamos


anteriormente indicando en el parámetro menu el otro objeto de la clase Menu:

menubar1.add_cascade(label="Colores", menu=opciones1)

De forma idéntica creamos el segundo menú desplegable:

opciones2 = tk.Menu(menubar1)
opciones2.add_command(label="640x480", command=self.ventanachica)
opciones2.add_command(label="1024x800", command=self.ventanagrande)
menubar1.add_cascade(label="Tamaños", menu=opciones2)

Cuando ejecutamos alguna de las opciones se dispara el método que hemos


configurado en el parámetro command, por ejemplo si seleccionamos 'Verde':
Variantes en un menú.
• Podemos agregar líneas separadoras entre opciones mediante la
llamada al método 'add_separator':

• opciones1 = tk.Menu(menubar1)

• opciones1.add_command(label="Rojo", command=self.fijarrojo)

• opciones1.add_command(label="Verde", command=self.fijarverde)

• opciones1.add_separator()

• opciones1.add_command(label="Azul", command=self.fijarazul)

La interfaz visual del menú queda con la siguiente apariencia:


• Los menú desplegables muestran una línea de puntos antes de la primer
opción. Si el operador hace clic sobre la misma el menú desplegable se
muestra en una barra de herramientas fuera de la ventana principal
(puede tener sentido si en un programa debemos seleccionar opciones
en forma muy seguida y no queremos tener que estar abriendo el menú
desplegable):

Si queremos evitar esta característica de los menú desplegables de


tkinter debemos pasar el parámetro 'tearoff' con el valor 0:

opciones1 = tk.Menu(menubar1, tearoff=0)


opciones1.add_command(label="Rojo", command=self.fijarrojo)
opciones1.add_command(label="Verde", command=self.fijarverde)
opciones1.add_separator()
opciones1.add_command(label="Azul", command=self.fijarazul)

Podemos comprobar que no aparece la línea de puntos:


• Otra posibilidad es agregar teclas de acceso rápido a opciones de
nuestro menú. Esto se resuelve la parte visual agregando el parámetro
'acelerator', y por otro lado asignar a cada una de las teclas de acceso
rápido la ejecución de un método:

• import tkinter as tk

• class Aplicacion:
• def __init__(self):
• self.ventana1=tk.Tk()
• menubar1 = tk.Menu(self.ventana1)
• self.ventana1.config(menu=menubar1)
• opciones1 = tk.Menu(menubar1, tearoff
=0)
• opciones1.add_command(label="Rojo", c
ommand=self.fijarrojo, accelerator="Ctrl+R")
• opciones1.add_command(label="Verde",
command=self.fijarverde, accelerator="Ctrl+V"
)
• opciones1.add_separator()
• opciones1.add_command(label="Azul", c
ommand=self.fijarazul, accelerator="Ctrl+A")
• self.ventana1.bind_all("<Control-r>",
self.cambiar)
• self.ventana1.bind_all("<Control-v>",
self.cambiar)
• self.ventana1.bind_all("<Control-a>",
self.cambiar)
• menubar1.add_cascade(label="Colores",
menu=opciones1)
• opciones2 = tk.Menu(menubar1)
• opciones2.add_command(label="640x480"
, command=self.ventanachica)
• opciones2.add_command(label="1024x800
", command=self.ventanagrande)
• menubar1.add_cascade(label="Tamaños",
menu=opciones2)
• self.ventana1.mainloop()

• def cambiar(self, event):


• if event.keysym=="r":
• self.fijarrojo()
• if event.keysym=="v":
• self.fijarverde()
• if event.keysym=="a":
• self.fijarazul()

• def fijarrojo(self):
• self.ventana1.configure(background="r
ed")

• def fijarverde(self):
• self.ventana1.configure(background="g
reen")

• def fijarazul(self):
• self.ventana1.configure(background="b
lue")

• def ventanachica(self):
• self.ventana1.geometry("640x480")

• def ventanagrande(self):
• self.ventana1.geometry("1024x800")

• aplicacion1=Aplicacion()
El método cambiar se ejecuta cuando presionamos al mismo tiempo la
tecla Ctrl y alguna de las otras teclas "R", "V" o "A":

• Podemos disponer dentro de un menú desplegable una opción que


despliegue otro submenú, la interfaz visual debe ser similar a esta:
El código en Python que implementa el menú de la imagen es:

import tkinter as tk

class Aplicacion:
def __init__(self):
self.ventana1=tk.Tk()
menubar1 = tk.Menu(self.ventana1)
self.ventana1.config(menu=menubar1)
opciones1 = tk.Menu(menubar1)
opciones1.add_command(label="Rojo", c
ommand=self.fijarrojo)
opciones1.add_command(label="Verde",
command=self.fijarverde)
opciones1.add_command(label="Azul", c
ommand=self.fijarazul)
menubar1.add_cascade(label="Colores",
menu=opciones1)
opciones2 = tk.Menu(menubar1)
opciones2.add_command(label="640x480"
, command=self.ventanachica)
opciones2.add_command(label="1024x800
", command=self.ventanagrande)
submenu1=tk.Menu(menubar1)
submenu1.add_command(label="1024x1024
", command=self.tamano1)
submenu1.add_command(label="1280x1024
", command=self.tamano2)
opciones2.add_cascade(label="Otros ta
maños", menu= submenu1)
menubar1.add_cascade(label="Tamaños",
menu=opciones2)
self.ventana1.mainloop()

def fijarrojo(self):
self.ventana1.configure(background="r
ed")

def fijarverde(self):
self.ventana1.configure(background="g
reen")

def fijarazul(self):
self.ventana1.configure(background="b
lue")

def ventanachica(self):
self.ventana1.geometry("640x480")

def ventanagrande(self):
self.ventana1.geometry("1024x800")

def tamano1(self):
self.ventana1.geometry("1024x1024")

def tamano2(self):
self.ventana1.geometry("1280x1024")

aplicacion1=Aplicacion()

Problema propuesto
• Mediante dos controles de tipo Entry permitir el ingreso de dos números.
Crear un menú que contenga una opción que cambie el tamaño de la
ventana con los valores ingresados por teclado. Finalmente disponer
otra opción que finalice el programa

Ver video
Solución

Retornar

66 - ttk : controles Notebook y Frame


La clase Notebook nos permite crear un cuaderno con una serie de pestañas
en la parte superior. En cada pestaña asociamos un objeto de la clase Frame y
dentro de esta podemos disponer distintos controles visuales que hemos visto
hasta ahora como pueden ser Label, Button, Radiobutton, Checkbutton, Entry
etc.
Un ejemplo visual de un Notebook es:
Según la pestaña seleccionada se muestra un Frame con distintos controles
visuales:

Problema:
Confeccionar una aplicación que muestre un cuaderno con tres pestañas. Los
títulos de cada pestaña deben ser 'Button', 'Label' y 'Entry'. Según la pestaña
seleccionada mostrar un mensaje informando el objetivo de la clase y un
ejemplo de la misma.
Programa: ejercicio243.py
Ver video

import tkinter as tk
from tkinter import ttk

class Aplicacion:
def __init__(self):
self.ventana1=tk.Tk()
self.ventana1.title("Prueba del control N
otebook")
self.cuaderno1 = ttk.Notebook(self.ventan
a1)

self.pagina1 = ttk.Frame(self.cuaderno1)
self.cuaderno1.add(self.pagina1, text="Bu
tton")
self.label1=ttk.Label(self.pagina1, text=
"La clase Button nos permite capturar el clic y l
anzar un método.")
self.label1.grid(column=0, row=0)
self.boton1=ttk.Button(self.pagina1, text
="Ejemplo de botón")
self.boton1.grid(column=0, row=1)
self.boton2=ttk.Button(self.pagina1, text
="Ejemplo de botón inactivo", state="disabled")
self.boton2.grid(column=0, row=2)

self.pagina2 = ttk.Frame(self.cuaderno1)
self.cuaderno1.add(self.pagina2, text="La
bel")
self.label2=ttk.Label(self.pagina2, text=
"La clase Label permite mostrar un mensaje en la
ventana")
self.label2.grid(column=0, row=0)
self.label3=ttk.Label(self.pagina2, text=
"con los caracteres \\n podemos hacer un salto de
línea dentro de la Label")
self.label3.grid(column=0, row=1)
self.pagina3 = ttk.Frame(self.cuaderno1)
self.cuaderno1.add(self.pagina3, text="En
try")
self.label4=ttk.Label(self.pagina3, text=
"""En tkinter el control de entrada de datos por
teclado se llama Entry.\n
Con este control aparece el típico recuadro que c
uando se le da foco aparece el cursor en forma in
termitente\n
esperando que el operador escriba algo por teclad
o.""")
self.label4.grid(column=0, row=0)
self.entry1=tk.Entry(self.pagina3, width=
30)
self.entry1.grid(column=0, row=1)

self.cuaderno1.grid(column=0, row=0)

self.ventana1.mainloop()

aplicacion1=Aplicacion()
Creamos un objeto de la clase Notebook y le pasamos como referencia la
ventana donde se mostrará:

self.cuaderno1 = ttk.Notebook(self.ventana1)

Creamos un objeto de la clase Frame y le pasamos como referencia el objeto


de la clase Notebook donde se insertará:

self.pagina1 = ttk.Frame(self.cuaderno1)
Añadimos el objeto de la clase Frame que acabamos de crear con el nombre
'pagina1' en el objeto 'cuaderno1' y en la propiedad 'text' indicamos el texto que
debe mostrar la pestaña:

self.cuaderno1.add(self.pagina1, text="Button")

Creamos una Label e indicamos que se agregue en el Frame 'pagina1' en lugar


de la ventana principal (esto cambia con lo visto anteriormente):

self.label1=ttk.Label(self.pagina1, text="La clase Button nos permite ca


pturar el clic y lanzar un método.")
self.label1.grid(column=0, row=0)

Lo mismo sucede con los dos botones que se agregan a 'pagina1', esto hace
que solo sean visibles cuando la primer pestaña esté seleccionada:

self.boton1=ttk.Button(self.pagina1, text="Ejemplo de botón")


self.boton1.grid(column=0, row=1)
self.boton2=ttk.Button(self.pagina1, text="Ejemplo de botón inactivo", s
tate="disabled")
self.boton2.grid(column=0, row=2)

De forma similar creamos las otras dos pestañas con sus respectivos 'Frame':

self.pagina2 = ttk.Frame(self.cuaderno1)
self.cuaderno1.add(self.pagina2, text="Label")
self.label2=ttk.Label(self.pagina2, text="La clase Label permite mostrar
un mensaje en la ventana")
self.label2.grid(column=0, row=0)
self.label3=ttk.Label(self.pagina2, text="con los caracteres \\n podemos
hacer un salto de línea dentro de la Label")
self.label3.grid(column=0, row=1)

self.pagina3 = ttk.Frame(self.cuaderno1)
self.cuaderno1.add(self.pagina3, text="Entry")
self.label4=ttk.Label(self.pagina3, text="""En tkinter el control de ent
rada de datos por teclado se llama Entry.\n
Con este control aparece el típico recuadro que cuando se le da foco aparece el
cursor en forma intermitente\n
esperando que el operador escriba algo por teclado.""")
self.label4.grid(column=0, row=0)
self.entry1=tk.Entry(self.pagina3, width=30)
self.entry1.grid(column=0, row=1)

No debemos olvidarnos de ubicar el Notebook con respecto a la ventana


principal:

self.cuaderno1.grid(column=0, row=0)

Retornar

67 - ttk : control LabelFrame


El control visual LabelFrame tiene una funcionalidad casi idéntica a la
componente Frame que vimos en el concepto anterior, la única diferencia es
que agrega un texto en la parte superior del Frame y hace un recuadro
alrededor del mismo.
El Widget LabelFrame es un contenedor donde podemos agregar en su interior
otros Widget como Button, Label, Entry, Radiobutton etc.
La representación visual de un LabelFrame que tiene 2 Label, 2 Entry y un
Button es:

Problema:
Confeccionar una aplicación que muestre dos controles de tipo LabelFrame. En
la primera disponer 2 Label, 2 Entry y un Button, en el segundo LabelFrame
disponer 3 botones.
La representación visual debe ser:
Programa: ejercicio244.py
Ver video

import tkinter as tk
from tkinter import ttk

class Aplicacion:
def __init__(self):
self.ventana1=tk.Tk()
self.labelframe1=ttk.LabelFrame(self.vent
ana1, text="Login:")
self.labelframe1.grid(column=0, row=0, pa
dx=5, pady=10)
self.login()
self.labelframe2=ttk.LabelFrame(self.vent
ana1, text="Operaciones")
self.labelframe2.grid(column=0, row=1, pa
dx=5, pady=10)
self.operaciones()
self.ventana1.mainloop()
def login(self):
self.label1=ttk.Label(self.labelframe1, t
ext="Nombre de usuario:")
self.label1.grid(column=0, row=0, padx=4,
pady=4)
self.entry1=ttk.Entry(self.labelframe1)
self.entry1.grid(column=1, row=0, padx=4,
pady=4)
self.label2=ttk.Label(self.labelframe1, t
ext="Ingrese clave:")
self.label2.grid(column=0, row=1, padx=4,
pady=4)
self.entry2=ttk.Entry(self.labelframe1, s
how="*")
self.entry2.grid(column=1, row=1, padx=4,
pady=4)
self.boton1=ttk.Button(self.labelframe1,
text="Ingresar")
self.boton1.grid(column=1, row=2, padx=4,
pady=4)

def operaciones(self):
self.boton2=ttk.Button(self.labelframe2,
text="Agregar usuario")
self.boton2.grid(column=0, row=0, padx=4,
pady=4)
self.boton3=ttk.Button(self.labelframe2,
text="Modificar usuario")
self.boton3.grid(column=1, row=0, padx=4,
pady=4)
self.boton4=ttk.Button(self.labelframe2,
text="Borrar usuario")
self.boton4.grid(column=2, row=0, padx=4,
pady=4)

aplicacion1=Aplicacion()
En el método __init__ inmediatamente luego de crear el objeto de la clase Tk
procedemos a crear el primer LabelFrame y ubicarlo dentro de la ventana:

self.ventana1=tk.Tk()
self.labelframe1=ttk.LabelFrame(self.ventana1, text="Login:")
self.labelframe1.grid(column=0, row=0, padx=5, pady=10)

Para no hacer todo el algoritmo dentro del método __init__ implementamos el


método login y desde acá hacemos su llamada:

self.login()

El algoritmo del método login tiene por objetivo crear las 2 Label, 2 Entry y
Button y añadirlos dentro del LabelFrame:

def login(self):
self.label1=ttk.Label(self.labelframe1, text="Nombre de usuario:")
self.label1.grid(column=0, row=0, padx=4, pady=4)
self.entry1=ttk.Entry(self.labelframe1)
self.entry1.grid(column=1, row=0, padx=4, pady=4)
self.label2=ttk.Label(self.labelframe1, text="Ingrese clave:")
self.label2.grid(column=0, row=1, padx=4, pady=4)
self.entry2=ttk.Entry(self.labelframe1, show="*")
self.entry2.grid(column=1, row=1, padx=4, pady=4)
self.boton1=ttk.Button(self.labelframe1, text="Ingresar")
self.boton1.grid(column=1, row=2, padx=4, pady=4)
Para que los controles no aparezcan pegados unos con otros utilizamos los
parámetros padx y pady.
De forma similar en el método __init__ creamos el segundo LabelFrame y
llamamos al método operaciones:

self.labelframe2=ttk.LabelFrame(self.ventana1, text="Operaciones")
self.labelframe2.grid(column=0, row=1, padx=5, pady=10)
self.operaciones()

El método operaciones crea los 3 Button y los agrega al segundo LabelFrame:

def operaciones(self):
self.boton2=ttk.Button(self.labelframe2, text="Agregar usuario")
self.boton2.grid(column=0, row=0, padx=4, pady=4)
self.boton3=ttk.Button(self.labelframe2, text="Modificar usuario")
self.boton3.grid(column=1, row=0, padx=4, pady=4)
self.boton4=ttk.Button(self.labelframe2, text="Borrar usuario")
self.boton4.grid(column=2, row=0, padx=4, pady=4)

El empleo de los LabelFrame nos permite crear interfaces visuales más claras
para los operadores de nuestro programa.
Si tenemos luego que hacer cambios de ubicación de los LabelFrame es muy
sencillo, solo cambiamos los valores que le pasamos a grid. Si queremos que
primero se muestre la barra de botones y luego el login:

Esta nueva representación visual se obtiene solo cambiando dos números de


fila:
def __init__(self):
self.ventana1=tk.Tk()
self.labelframe1=ttk.LabelFrame(self.ventana1, text="Login:")
self.labelframe1.grid(column=0, row=1, padx=5, pady=10)
self.login()
self.labelframe2=ttk.LabelFrame(self.ventana1, text="Operaciones")
self.labelframe2.grid(column=0, row=0, padx=5, pady=10)
self.operaciones()
self.ventana1.mainloop()

Problema propuesto
• Mediante dos controles de tipo LabelFrame implementar la siguiente
interfaz visual:

Ver video
Solución

Retornar
68 - tkinter : Layout Manager
(administrador de diseño)
Una de las herramientas fundamentales cuando armamos interfaces visuales
es la metodología que utilizamos para disponer los controles dentro del
formulario. Hasta ahora hemos utilizado el administrador de diseño Grid.
En la librería GUI tkinter disponemos de tres Layout Manager para disponer
controles dentro de una ventana:

1. Grid
2. Pack
3. Place

Solo se puede utilizar uno de estos Layout Manager dentro de un contenedor,


recordemos que un contenedor puede ser la ventana propiamente dicha, un
Frame o un LabelFrame.
El gestor de diseño más completo y que se adapta en la mayoría de las
situaciones es el Grid, pero podemos en muchos casos crear Frame o
LabelFrame y definir dentro de estos Layout Manager de tipo Pack o Place.

Layout Manager: Pack


Veamos con un ejemplo como se ubican los Widget utilizando Pack.

Problema:
Disponer una serie de botones utilizando el Layout Manager de tipo Pack.
La representación visual debe ser:

Programa: ejercicio246.py
Ver video
import tkinter as tk
from tkinter import ttk

class Aplicacion:
def __init__(self):
self.ventana1=tk.Tk()
self.boton1=ttk.Button(self.ventana1, tex
t="Boton 1")
self.boton1.pack(side=tk.TOP, fill=tk.BOT
H)
self.boton2=ttk.Button(self.ventana1, tex
t="Boton 2")
self.boton2.pack(side=tk.TOP, fill=tk.BOT
H)
self.boton3=ttk.Button(self.ventana1, tex
t="Boton 3")
self.boton3.pack(side=tk.TOP, fill=tk.BOT
H)
self.boton4=ttk.Button(self.ventana1, tex
t="Boton 4")
self.boton4.pack(side=tk.LEFT)
self.boton5=ttk.Button(self.ventana1, tex
t="Boton 5")
self.boton5.pack(side=tk.RIGHT)
self.boton6=ttk.Button(self.ventana1, tex
t="Boton 6")
self.boton6.pack(side=tk.RIGHT)
self.boton7=ttk.Button(self.ventana1, tex
t="Boton 7")
self.boton7.pack(side=tk.RIGHT)
self.ventana1.mainloop()

aplicacion1=Aplicacion()
Para ubicar los controles empleando el administrador de diseños Pack
utilizamos el método 'pack' que cuenta con una serie de parámetros.
El boton1 se ubica en la parte superior de la ventana ya que en el parámetro
side hemos pasado la contante tk.TOP:

self.boton1=ttk.Button(self.ventana1, text="Boton 1")


self.boton1.pack(side=tk.TOP, fill=tk.BOTH)

Si no especificamos el parámetro fill luego el botón ocupa solo el espacio


necesario y no se expande:

self.boton1=ttk.Button(self.ventana1, text="Boton 1")


self.boton1.pack(side=tk.TOP)

El segundo y tercer botón se ubican debajo del primero porque también en el


parámetro side hemos pasado el valor 'tk.TOP':

self.boton2=ttk.Button(self.ventana1, text="Boton 2")


self.boton2.pack(side=tk.TOP, fill=tk.BOTH)
self.boton3=ttk.Button(self.ventana1, text="Boton 3")
self.boton3.pack(side=tk.TOP, fill=tk.BOTH)

El cuarto botón hemos indicado en el parámetro side el valor 'tk.LEFT' y los


siguientes botones el valor 'tk.RIGHT':

self.boton4=ttk.Button(self.ventana1, text="Boton 4")


self.boton4.pack(side=tk.LEFT)
self.boton5=ttk.Button(self.ventana1, text="Boton 5")
self.boton5.pack(side=tk.RIGHT)
self.boton6=ttk.Button(self.ventana1, text="Boton 6")
self.boton6.pack(side=tk.RIGHT)
self.boton7=ttk.Button(self.ventana1, text="Boton 7")
self.boton7.pack(side=tk.RIGHT)

Si agrandamos la ventana podemos ver que el botón fijado a izquierda siempre


permanece en dicho lugar y los fijados a derecha se desplazan:

El parámetro side puede recibir alguno de estos cuatro valores:

• tk.TOP

• tk.LEFT

• tk.RIGHT

• tk.BOTTOM

Podemos pasar los parámetros padx y pady para dejar espacio entre los
controles visuales y el borde del contenedor:
Para lograr ese resultado debemos hacer los siguientes cambios:

import tkinter as tk
from tkinter import ttk

class Aplicacion:
def __init__(self):
self.ventana1=tk.Tk()
self.boton1=ttk.Button(self.ventana1, tex
t="Boton 1")
self.boton1.pack(side=tk.TOP, fill=tk.BOT
H, padx=5, pady=5)
self.boton2=ttk.Button(self.ventana1, tex
t="Boton 2")
self.boton2.pack(side=tk.TOP, fill=tk.BOT
H, padx=15, pady=15)
self.boton3=ttk.Button(self.ventana1, tex
t="Boton 3")
self.boton3.pack(side=tk.TOP, fill=tk.BOT
H, padx=25, pady=25)
self.boton4=ttk.Button(self.ventana1, tex
t="Boton 4")
self.boton4.pack(side=tk.LEFT)
self.boton5=ttk.Button(self.ventana1, tex
t="Boton 5")
self.boton5.pack(side=tk.RIGHT, padx=10)
self.boton6=ttk.Button(self.ventana1, tex
t="Boton 6")
self.boton6.pack(side=tk.RIGHT)
self.boton7=ttk.Button(self.ventana1, tex
t="Boton 7")
self.boton7.pack(side=tk.RIGHT)
self.ventana1.mainloop()

aplicacion1=Aplicacion()

Layout Manager: Grid


Este tipo de Layout Manager lo hemos estado utilizando en muchos conceptos
anteriores, veremos otras posibilidades que nos suministra.
Este tipo de Layout define una tabla con columnas y filas, cada vez que
agregamos un Widget indicamos en que columna y fila se debe ubicar:

Un tema que no vimos es que podemos expandir celdas de la tabla para que
se ocupen más de una columna o más de una fila.

Problema:
Disponer una serie de botones utilizando el Layout Manager de tipo Grid.
La representación visual debe ser:

Programa: ejercicio247.py
Ver video

import tkinter as tk
from tkinter import ttk

class Aplicacion:
def __init__(self):
self.ventana1=tk.Tk()
self.boton1=ttk.Button(self.ventana1, tex
t="Boton 1")
self.boton1.grid(column=0, row=0)
self.boton2=ttk.Button(self.ventana1, tex
t="Boton 2")
self.boton2.grid(column=1, row=0)
self.boton3=ttk.Button(self.ventana1, tex
t="Boton 3")
self.boton3.grid(column=2, row=0, rowspan
=2, sticky="ns")
self.boton4=ttk.Button(self.ventana1, tex
t="Boton 4")
self.boton4.grid(column=0, row=1)
self.boton5=ttk.Button(self.ventana1, tex
t="Boton 5")
self.boton5.grid(column=1, row=1)
self.boton6=ttk.Button(self.ventana1, tex
t="Boton 6")
self.boton6.grid(column=0, row=2, columns
pan=3, sticky="we")
self.ventana1.mainloop()

aplicacion1=Aplicacion()
Los dos primeros botones como ocupan una celda única no varía con lo que
hemos visto hasta ahora:

self.boton1=ttk.Button(self.ventana1, text="Boton 1")


self.boton1.grid(column=0, row=0)
self.boton2=ttk.Button(self.ventana1, text="Boton 2")
self.boton2.grid(column=1, row=0)

El tercer botón si lo expandimos para que ocupe dos filas:

self.boton3=ttk.Button(self.ventana1, text="Boton 3")


self.boton3.grid(column=2, row=0, rowspan=2, sticky="ns")

En la propiedad sticky (se traduce como 'pegajoso') pedimos que el botón se


expanda de north (norte) a south (sur), si no disponemos sticky luego el botón
ocupa las dos celdas pero aparece centrado.
El cuarto y quinto botón ocupan celdas individuales:

self.boton4=ttk.Button(self.ventana1, text="Boton 4")


self.boton4.grid(column=0, row=1)
self.boton5=ttk.Button(self.ventana1, text="Boton 5")
self.boton5.grid(column=1, row=1)

Finalmente el último botón se expande a tres columnas:

self.boton6=ttk.Button(self.ventana1, text="Boton 6")


self.boton6.grid(column=0, row=2, columnspan=3, sticky="we")

En el parámetro sticky indicamos que se estire de west (oeste) a east (este)

Layout Manager: Place


Este tipo de Layout Manager nos permite disponer un Widget en una posición y
con un tamaño con valor absoluto a nivel de píxeles. Hay que tener cuidado en
que casos utilizar este tipo de administrador de diseños ya que si agrandamos
o reducimos el tamaño de la ventana puede ser que los controles queden fuera
de la ventana y el operador no pueda visualizarlos.

Problema:
Disponer dos botones en la parte inferior derecha de la ventana utilizando el
Layout Manager de tipo Place. El ancho y alto de la ventana debe ser de 800
por 600 píxeles.
La representación visual debe ser:

Programa: ejercicio248.py
Ver video

import tkinter as tk
from tkinter import ttk

class Aplicacion:
def __init__(self):
self.ventana1=tk.Tk()
self.ventana1.geometry("800x600")
self.ventana1.resizable(0,0)
self.boton1=ttk.Button(self.ventana1, tex
t="Confirmar")
self.boton1.place(x=680, y=550, width=90,
height=30)
self.boton2=ttk.Button(self.ventana1, tex
t="Cancelar")
self.boton2.place(x=580, y=550, width=90,
height=30)
self.ventana1.mainloop()

aplicacion1=Aplicacion()
Creamos una ventana de 800x600 píxeles:

self.ventana1.geometry("800x600")

No permitimos que el operador la redimensione con el mouse (esto debido a


que si reduce el tamaño los botones quedarán fuera de la ventana):

self.ventana1.resizable(0,0)

Al botón que tiene la etiqueta "Confirmar" lo ubicamos en la columna 680


(indicado en píxeles) y la fila 550, también definimos el ancho y alto:

self.boton1=ttk.Button(self.ventana1, text="Confirmar")
self.boton1.place(x=680, y=550, width=90, height=30)

La ubicación del segundo botón queda con los siguientes valores:

self.boton2=ttk.Button(self.ventana1, text="Cancelar")
self.boton2.place(x=580, y=550, width=90, height=30)

Podemos utilizar el método 'place' para ubicar cualquiera de los controles


visuales que hemos visto hasta ahora: Button, Label, Entry, etc.

Recomendación
Siempre que tenga que implementar una interfaz gráfica es conveniente que en
un papel se haga un croquis y a partir de este agrupar controles relacionados
dentro de Frame o LabelFrame.

Retornar

69 - tkinter.messagebox : ventanas de
mensajes
Las aplicaciones de escritorio es muy común la necesidad de abrir otras
ventanas emergentes con el objetivo de informar, advertir de errores etc.
La librería tkinter provee un paquete llamado messagebox con una serie de
funciones para la apertura de diálogos de información.
Para usar estos diálogos lo primero que debemos hacer es importar el
paquete:

from tkinter import messagebox as mb

Podemos crear un alias para el nombre del paquete para no tener que escribir
messagebox todas las veces.

Problema:
Confeccionar una aplicación que permita ingresar dos valores enteros y al
presionar un botón nos muestre la suma en el título de la ventana. Si el
operador no ingresa en alguno de los dos controles Entry datos informar
mediante un diálogo el error que se está cometiendo.
Agregar además un menú de opciones que al ser seleccionado nos muestre
información del programa.
La representación visual cuando se presiona el botón "sumar" y no se ingresa
alguno de los dos números debe ser:
La representación visual cuando se abre el diálogo que informa sobre el
programa desde el menú de opciones es:

Programa: ejercicio249.py
Ver video
import tkinter as tk
from tkinter import ttk
from tkinter import messagebox as mb

class Aplicacion:
def __init__(self):
self.ventana1=tk.Tk()
self.labelframe1=ttk.LabelFrame(self.vent
ana1, text="Suma de números")
self.labelframe1.grid(column=0, row=0, pa
dx=10, pady=10)
self.agregar_componentes()
self.agregar_menu()
self.ventana1.mainloop()

def agregar_componentes(self):
self.label1=ttk.Label(self.labelframe1, t
ext="Ingrese primer valor:")
self.label1.grid(column=0, row=0, padx=5,
pady=5, sticky="e")
self.dato1=tk.StringVar()
self.entry1=ttk.Entry(self.labelframe1, t
extvariable=self.dato1)
self.entry1.grid(column=1, row=0, padx=5,
pady=5)
self.label2=ttk.Label(self.labelframe1, t
ext="Ingrese segundo valor:")
self.label2.grid(column=0, row=1, padx=5,
pady=5, sticky="e")
self.dato2=tk.StringVar()
self.entry2=ttk.Entry(self.labelframe1, t
extvariable=self.dato2)
self.entry2.grid(column=1, row=1, padx=5,
pady=5)
self.boton1=ttk.Button(self.labelframe1,
text="Sumar", command=self.sumar)
self.boton1.grid(column=1, row=2, padx=5,
pady=5, sticky="we")

def agregar_menu(self):
self.menubar1 = tk.Menu(self.ventana1)
self.ventana1.config(menu=self.menubar1)
self.opciones1 = tk.Menu(self.menubar1, t
earoff=0)
self.opciones1.add_command(label="Acerca
de...", command=self.acerca)
self.menubar1.add_cascade(label="Opciones
", menu=self.opciones1)

def sumar(self):
if self.dato1.get()=="" or self.dato2.get
()=="":
mb.showerror("Cuidado","No puede deja
r los cuadros de entrada de números vacíos")
else:
suma=int(self.dato1.get())+int(self.d
ato2.get())
self.ventana1.title("La suma es "+str
(suma))
def acerca(self):
mb.showinfo("Información", "Este programa
fue desarrollado para el aprendizaje de Python y
tkinter.")

aplicacion1=Aplicacion()
Creamos un objeto de la clase LabelFrame para disponer los controles de
entrada de dato y el botón de sumar:

self.labelframe1=ttk.LabelFrame(self.ventana1, text="Suma de números")


self.labelframe1.grid(column=0, row=0, padx=10, pady=10)
self.agregar_componentes()

El método agregar_componentes es donde creamos cada uno de los Widget y


los agregamos al LabelFrame:

def agregar_componentes(self):
self.label1=ttk.Label(self.labelframe1, text="Ingrese primer valor:")
self.label1.grid(column=0, row=0, padx=5, pady=5, sticky="e")
self.dato1=tk.StringVar()
self.entry1=ttk.Entry(self.labelframe1, textvariable=self.dato1)
self.entry1.grid(column=1, row=0, padx=5, pady=5)
self.label2=ttk.Label(self.labelframe1, text="Ingrese segundo valor:")
self.label2.grid(column=0, row=1, padx=5, pady=5, sticky="e")
self.dato2=tk.StringVar()
self.entry2=ttk.Entry(self.labelframe1, textvariable=self.dato2)
self.entry2.grid(column=1, row=1, padx=5, pady=5)
self.boton1=ttk.Button(self.labelframe1, text="Sumar", command=self.suma
r)
self.boton1.grid(column=1, row=2, padx=5, pady=5, sticky="we")

Para no codificar el menú de opciones todo en el método __init__ procedemos


a separarlo en el método agregar_menu:

def agregar_menu(self):
self.menubar1 = tk.Menu(self.ventana1)
self.ventana1.config(menu=self.menubar1)
self.opciones1 = tk.Menu(self.menubar1, tearoff=0)
self.opciones1.add_command(label="Acerca de...", command=self.acerca)
self.menubar1.add_cascade(label="Opciones", menu=self.opciones1)

Cuando se presiona el botón "Sumar" se ejecuta el método 'sumar' donde


verificamos mediante un if si alguno de los Entry se encuentra vacio:

def sumar(self):
if self.dato1.get()=="" or self.dato2.get()=="":
mb.showerror("Cuidado","No puede dejar los cuadros de entrada de núm
eros vacíos")
else:
suma=int(self.dato1.get())+int(self.dato2.get())
self.ventana1.title("La suma es "+str(suma))

Si alguno de los Entry se encuentra vacío se ejecuta el verdadero del if donde


llamamos a la función 'showerror' del paquete messagebox:

mb.showerror("Cuidado","No puede dejar los cuadros de entrada de núm


eros vacíos")

Esta función tiene dos parámetros, el primero es el mensaje del título y el


segundo el cuerpo propiamente del mensaje.
Por otro lado cuando se selecciona la opción del menú "Acerca de..." se
ejecuta el método acerca:

def acerca(self):
mb.showinfo("Información", "Este programa fue desarrollado para el apren
dizaje de Python y tkinter.")

En este método llamamos a la función showinfo del paquete messagebox y le


pasamos dos string para el título y el cuerpo del diálogo.
La diferencia entre los cuadros de diálogos 'showerror' y 'showinfo' es el ícono
gráfico que aparece en cada uno.
Existe otra función similar en este módulo llamado 'showwarning' (dispone otro
ícono en el diálogo):
Diálogos para confirmar o rechazar.
El paquete 'messagebox' cuenta con otra función que nos muestra un diálogo
con dos botones con los mensajes "Si" o "No", luego desde nuestro programa
podemos identificar cual de los dos botones se ha presionado.

Problema:
Confeccionar un programa que tenga solo un menú de opciones que al ser
presionado nos muestre un cuadro de mensaje que informe si queremos
finalizar la ejecución del programa. Si se presiona "si" se finaliza el programa
en caso contrario no se hace nada.
La representación visual luego de seleccionar la opción del menú es:

Programa: ejercicio250.py
Ver video

import tkinter as tk
from tkinter import messagebox as mb
import sys

class Aplicacion:
def __init__(self):
self.ventana1=tk.Tk()
self.agregar_menu()
self.ventana1.mainloop()

def agregar_menu(self):
self.menubar1 = tk.Menu(self.ventana1)
self.ventana1.config(menu=self.menubar1)
self.opciones1 = tk.Menu(self.menubar1, t
earoff=0)
self.opciones1.add_command(label="Salir",
command=self.salir)
self.menubar1.add_cascade(label="Opciones
", menu=self.opciones1)

def salir(self):
respuesta=mb.askyesno("Cuidado", "¿Quiere
salir del programa?")
if respuesta==True:
sys.exit()

aplicacion1=Aplicacion()
Cuando se selecciona la opción "Salir" del menú se ejecuta el método 'salir':

self.opciones1.add_command(label="Salir", command=self.salir)

En el método 'salir' llamamos a la función 'askyesno' del paquete 'messagebox':

def salir(self):
respuesta=mb.askyesno("Cuidado", "¿Quiere salir del programa?")
if respuesta==True:
sys.exit()

La función 'askyesno' retorna True o False según cual de los botones se ha


presionado. Si retorna True significa que se presionó el botón 'Si'

Retornar

70 - tkinter : ventanas de diálogos


Vimos en el concepto anterior que tkinter nos provee una serie de diálogos
para mostrar mensajes de información y error. En muchas situaciones
podemos necesitar crear otras ventanas con más funcionalidades que los
simples ventanas de mensajes.
Para crear diálogos en tkinter debemos crear un objeto de la clase TopLevel y
pasar como parámetro la referencia de la ventana principal.
Un diálogo se asemeja mucho a lo que es la ventana principal, podemos
disponer dentro de la misma objetos de la clase Label, Button, Entry etc.
Lo más común es que un diálogo tenga por objetivo la entrada de datos para
luego ser utilizados en la ventana principal.

Problema:
Confeccionar una aplicación que muestre un diálogo cuando se seleccione una
opción de un menú.
El dialogo debe solicitar el ingreso de dos enteros que se utilizarán en la
ventana principal para redimensionarla.
La representación visual de la ventana principal es muy sencilla:
Cuando se abre el diálogo tenemos la siguiente imagen:

Programa: ejercicio251.py
Ver video

import tkinter as tk
from tkinter import ttk

class Aplicacion:
def __init__(self):
self.ventana1=tk.Tk()
self.agregar_menu()
self.ventana1.mainloop()

def agregar_menu(self):
self.menubar1 = tk.Menu(self.ventana1)
self.ventana1.config(menu=self.menubar1)
self.opciones1 = tk.Menu(self.menubar1, t
earoff=0)
self.opciones1.add_command(label="Configu
rar ventana", command=self.configurar)
self.menubar1.add_cascade(label="Opciones
", menu=self.opciones1)

def configurar(self):
dialogo1 = DialogoTamano(self.ventana1)
s=dialogo1.mostrar()
self.ventana1.geometry(s[0]+"x"+s[1])

class DialogoTamano:

def __init__(self, ventanaprincipal):


self.dialogo=tk.Toplevel(ventanaprincipal
)
self.label1=ttk.Label(self.dialogo, text=
"Ingrese ancho:")
self.label1.grid(column=0, row=0, padx=5,
pady=5)
self.dato1=tk.StringVar()
self.entry1=ttk.Entry(self.dialogo, textv
ariable=self.dato1)
self.entry1.grid(column=1, row=0, padx=5,
pady=5)
self.entry1.focus()
self.label2=ttk.Label(self.dialogo, text=
"Ingrese alto:")
self.label2.grid(column=0, row=1, padx=5,
pady=5)
self.dato2=tk.StringVar()
self.entry2=ttk.Entry(self.dialogo, textv
ariable=self.dato2)
self.entry2.grid(column=1, row=1, padx=5,
pady=5)
self.boton1=ttk.Button(self.dialogo, text
="Confirmar", command=self.confirmar)
self.boton1.grid(column=1, row=2, padx=5,
pady=5)
self.dialogo.protocol("WM_DELETE_WINDOW",
self.confirmar)
self.dialogo.resizable(0,0)
self.dialogo.grab_set()

def mostrar(self):
self.dialogo.wait_window()
return (self.dato1.get(), self.dato2.get(
))
def confirmar(self):
self.dialogo.destroy()

aplicacion1=Aplicacion()
Para resolver este problema hemos declarado dos clases, la primer que
muestra la ventana principal:

import tkinter as tk
from tkinter import ttk

class Aplicacion:
def __init__(self):
self.ventana1=tk.Tk()
self.agregar_menu()
self.ventana1.mainloop()

Separamos la creación del menú en otro método:

def agregar_menu(self):
self.menubar1 = tk.Menu(self.ventana1)
self.ventana1.config(menu=self.menubar1)
self.opciones1 = tk.Menu(self.menubar1, tearoff=0)
self.opciones1.add_command(label="Configurar ventana", command=self.conf
igurar)
self.menubar1.add_cascade(label="Opciones", menu=self.opciones1)

Cuando se selecciona la opción del menú "Configurar ventana" se dispara el


método "configurar".
Creamos un objeto de la clase DialogoTamano y le pasamos como parámetro
la referencia de la ventana principal:

def configurar(self):
dialogo1 = DialogoTamano(self.ventana1)
Inmediatamente luego de crear el diálogo llamamos al método 'mostrar' donde
se quedará ejecutando la aplicación hasta que el operador cierre el diálogo:

s=dialogo1.mostrar()

Una vez que el operador cierra el diálogo el método 'mostrar' retorna una tupla
con los dos valores ingresados por teclado, estos los usamos para dimensionar
la ventana principal:

self.ventana1.geometry(s[0]+"x"+s[1])

Ahora analicemos la clase DialogoTamano, en el método __init__ recibimos


como parámetro la referencia de la ventana principal:

class DialogoTamano:

def __init__(self, ventanaprincipal):

Creamos un diálogo mediante la clase TopLevel que requiera la referencia de


la ventana principal:

self.dialogo=tk.Toplevel(ventanaprincipal)

Creamos seguidamente todos los controles visuales que tendrá el diálogo de la


misma manera que hacemos con la ventana principal:

self.label1=ttk.Label(self.dialogo, text="Ingrese ancho:")


self.label1.grid(column=0, row=0, padx=5, pady=5)
self.dato1=tk.StringVar()
self.entry1=ttk.Entry(self.dialogo, textvariable=self.dato1)
self.entry1.grid(column=1, row=0, padx=5, pady=5)
self.entry1.focus()
self.label2=ttk.Label(self.dialogo, text="Ingrese alto:")
self.label2.grid(column=0, row=1, padx=5, pady=5)
self.dato2=tk.StringVar()
self.entry2=ttk.Entry(self.dialogo, textvariable=self.dato2)
self.entry2.grid(column=1, row=1, padx=5, pady=5)
self.boton1=ttk.Button(self.dialogo, text="Confirmar", command=self.conf
irmar)
self.boton1.grid(column=1, row=2, padx=5, pady=5)
Con la siguiente línea indicamos que método debe ejecutarse si el operador
presiona la 'x' de cerrado del diálogo:

self.dialogo.protocol("WM_DELETE_WINDOW", self.confirmar)

Es común no permitir el cambio de tamaño del diálogo con las flechas del
mouse:

self.dialogo.resizable(0,0)

Mediante la llamada al método 'grab_set' desactivamos los eventos en la


ventana principal, es decir que hasta que el operador no cierre el diálogo la
ventana principal aparecerá inactiva:

self.dialogo.grab_set()

El método 'mostrar' hace visible el diálogo y cuando se cierra retorna la tupla:

def mostrar(self):
self.dialogo.wait_window()
return (self.dato1.get(), self.dato2.get())

Finalmente el método 'confirmar' cierra el diálogo y permite que finalice el


método 'mostrar' retornando los dos enteros:

def confirmar(self):
self.dialogo.destroy()

Retornar

71 - ttk : control Spinbox


Este control visual es muy utilizado para seleccionar un valor de una lista. Se
dispone de dos botones para subir o bajar en la lista de valores posibles:

Se pueden mostrar listas de valores de tipo string.


Problema:
En una aduana hay una máquina que sortea las personas cuyo equipaje serán
revisados.
La persona selecciona la cantidad de bultos (hacer dicha selección mediante
un Spinbox)
Luego se presiona el botón sortear y aparece al lado de este botón una Label
de color rojo o verde (En caso de ser rojo se revisa su equipaje, en caso de ser
verde, no se revisa)
Para el sorteo generar un valor aleatorio entre 1 y 3. Si se genera un 1 se
revisa, si se genera un 2 o 3 no se revisa, mostrar un mensaje de error si el
Spinbox tiene un cero.
La interfaz visual debe ser similar a esta:

Programa: ejercicio252.py
Ver video

import tkinter as tk
from tkinter import ttk
from tkinter import messagebox as mb
import random

class Aplicacion:
def __init__(self):
self.ventana1=tk.Tk()
self.label1=ttk.Label(self.ventana1, text
="Seleccione la cantidad de bultos:")
self.label1.grid(column=0, row=0, padx=10
, pady=10)
self.spinbox1=ttk.Spinbox(self.ventana1,
from_=0, to=100, width=10, state='readonly')
self.spinbox1.set(0)
self.spinbox1.grid(column=1, row=0, padx=
10, pady=10)
self.boton1=ttk.Button(self.ventana1, tex
t="Sortear", command=self.sortear)
self.boton1.grid(column=0, row=1, padx=10
, pady=10)
self.label2=ttk.Label(self.ventana1, text
="", width=20)
self.label2.grid(column=1, row=1, padx=10
, pady=10)
self.ventana1.mainloop()

def sortear(self):
if int(self.spinbox1.get())==0:
mb.showerror("Cuidado","Debe seleccio
nar un valor distinto a cero en bultos")
else:
valor=random.randint(1,3)
if valor==1:
self.label2.configure(text="Se de
ben revisar")
self.label2.configure(background=
"red")
else:
self.label2.configure(text="No se
revisan")
self.label2.configure(background=
"green")

aplicacion1=Aplicacion()
Cuando creamos el Spinbox pasamos el parámetro 'from_' con el valor inicial y
el parámetro 'to' con el valor final (el nombre tan extraño de 'from_' se debe a
que Python tiene una palabra reservada con dicho nombre):

self.spinbox1=ttk.Spinbox(self.ventana1, from_=0, to=100, width=10, stat


e='readonly')

Mediante el método set indicamos el valor inicial que muestra el Spinbox:

self.spinbox1.set(0)

Cuando se presiona el botón "sortear" se ejecuta el método 'sortear' donde


primero verificamos si el Spinbox tiene el valor cero seleccionado, en caso
afirmativo mostramos un mensaje de error:

def sortear(self):
if int(self.spinbox1.get())==0:
mb.showerror("Cuidado","Debe seleccionar un valor distinto a cero en
bultos")

En el caso que el operador eligió un valor distinto a cero procedemos a generar


un valor aleatorio entre 1 y 3. Según el valor aleatorio generado procedemos a
modificar el color de fondo de la label:

valor=random.randint(1,3)
if valor==1:
self.label2.configure(text="Se deben revisar")
self.label2.configure(background="red")
else:
self.label2.configure(text="No se revisan")
self.label2.configure(background="green")

Acotaciones
• Si queremos llenar el Spinbox con valores no consecutivos, sino de 3 en
3 podemos utilizar la siguiente sintaxis:
• self.spinbox1=ttk.Spinbox(self.ventana1, increment=3, from_=1, to=10, sta
te='readonly')

• Podemos definir una tupla y luego inicializar el parámetro values:

• dias=("lunes", "martes", "miércoles","jueves","viernes","sábado","domingo


")

• self.spinbox1=ttk.Spinbox(self.ventana1, values=dias, state='readonly')

• self.spinbox1.set(dias[0])

Retornar

72 - tkinter.ScrolledText : editor
multilínea
Hemos visto anteriormente el control Entry que nos permite ingresar una
cadena de caracteres por teclado. El Widget ScrolledText es similar al Widget
Entry con la salvedad que nos permite ingresar múltiples líneas.
Cuenta con métodos sofisticados para extraer trozos del texto ingresado en la
componente.
Para poder utilizar esta nueva componente debemos importar el módulo
scrolledtext del paquete tkinter (podemos crear un alias para no tener que
escribir scrolledtext):

from tkinter import scrolledtext as st

Problema:
Confeccionar un programa que contenga dos controles de tipo ScrolledText. En
el primero ingresamos por teclado cualquier texto. Mediante 4 controles de tipo
Entry indicar desde que fila y columna hasta que fila y columna extraer
caracteres del primer ScrolledText y copiarlos al segundo ScrolledText cuando
se presione un botón.
La interfaz visual debe ser similar a esta:
Programa: ejercicio253.py
Ver video

import tkinter as tk
from tkinter import ttk
from tkinter import scrolledtext as st

class Aplicacion:
def __init__(self):
self.ventana1=tk.Tk()
self.scrolledtext1=st.ScrolledText(self.v
entana1, width=50, height=10)
self.scrolledtext1.grid(column=0,row=0, p
adx=10, pady=10)
self.framecopia()
self.scrolledtext2=st.ScrolledText(self.v
entana1, width=50, height=10)
self.scrolledtext2.grid(column=0,row=2, p
adx=10, pady=10)
self.ventana1.mainloop()

def framecopia(self):
self.labelframe1=ttk.LabelFrame(self.vent
ana1, text="Region")
self.labelframe1.grid(column=0, row=1, pa
dx=5, pady=5, sticky="w")
self.label1=ttk.Label(self.labelframe1, t
ext="Desde fila:")
self.label1.grid(column=0, row=0, padx=5,
pady=5, sticky="e")
self.dato1=tk.StringVar()
self.entry1=ttk.Entry(self.labelframe1, t
extvariable=self.dato1)
self.entry1.grid(column=1, row=0, padx=5,
pady=5, sticky="e")
self.label2=ttk.Label(self.labelframe1, t
ext="Desde columna:")
self.label2.grid(column=0, row=1, padx=5,
pady=5, sticky="e")
self.dato2=tk.StringVar()
self.entry2=ttk.Entry(self.labelframe1, t
extvariable=self.dato2)
self.entry2.grid(column=1, row=1, padx=5,
pady=5, sticky="e")

self.label3=ttk.Label(self.labelframe1, t
ext="Hasta fila:")
self.label3.grid(column=0, row=2, padx=5,
pady=5, sticky="e")
self.dato3=tk.StringVar()
self.entry3=ttk.Entry(self.labelframe1, t
extvariable=self.dato3)
self.entry3.grid(column=1, row=2, padx=5,
pady=5, sticky="e")
self.label4=ttk.Label(self.labelframe1, t
ext="Hasta columna:")
self.label4.grid(column=0, row=3, padx=5,
pady=5, sticky="e")
self.dato4=tk.StringVar()
self.entry4=ttk.Entry(self.labelframe1, t
extvariable=self.dato4)
self.entry4.grid(column=1, row=3, padx=5,
pady=5, sticky="e")

self.boton1=ttk.Button(self.labelframe1,
text="Copiar", command=self.copiar)
self.boton1.grid(column=1, row=4, padx=10
, pady=10)

def copiar(self):
iniciofila=self.dato1.get()
iniciocolumna=self.dato2.get()
finfila=self.dato3.get()
fincolumna=self.dato4.get()
datos=self.scrolledtext1.get(iniciofila+"
."+iniciocolumna, finfila+"."+fincolumna)
self.scrolledtext2.delete("1.0", tk.END)
self.scrolledtext2.insert("1.0", datos)

aplicacion1=Aplicacion()
Lo primero que hacemos es importar el módulo scrolledtext del paquete tkinter
y definir un alias:

from tkinter import scrolledtext as st

Creamos y ubicamos cada uno de los ScrolledText en el método __init__:

def __init__(self):
self.ventana1=tk.Tk()
self.scrolledtext1=st.ScrolledText(self.ventana1, width=50, height=10)
self.scrolledtext1.grid(column=0,row=0, padx=10, pady=10)
self.framecopia()
self.scrolledtext2=st.ScrolledText(self.ventana1, width=50, height=10)
self.scrolledtext2.grid(column=0,row=2, padx=10, pady=10)
self.ventana1.mainloop()
Separamos en el método framecopia la creación de la interfaz visual donde se
cargan los 4 valores.
El método fundamental es el 'copiar':

def copiar(self):
iniciofila=self.dato1.get()
iniciocolumna=self.dato2.get()
finfila=self.dato3.get()
fincolumna=self.dato4.get()
datos=self.scrolledtext1.get(iniciofila+"."+iniciocolumna, finfila+"."+f
incolumna)
self.scrolledtext2.delete("1.0", tk.END)
self.scrolledtext2.insert("1.0", datos)

Para extraer cadenas de caracteres de un control ScrolledText debemos llamar


la método get y pasar dos String. Por ejemplo si queremos extraer todos los
caracteres de la primer fila hasta los 10 primeros caracteres de la tercer fila
deberemos codificar:

datos=self.scrolledtext1.get("1.0", "3.10") #fila 1 columna 0 hasta fi


la 3 columna 10

En nuestro problema estos cuatro números los estamos cargando por teclado
en los controles Entry.
Para borrar todo el contenido de un ScrolledText debemos llamar al método
delete y pasar estos dos parámetros:

self.scrolledtext2.delete("1.0", tk.END)

Para insertar en cualquier parte de un ScrolledText empleamos el método


insert:

self.scrolledtext2.insert("1.0", datos)

Retornar
73 - tkinter : control Canvas
El control Canvas nos permite acceder a una serie de primitivas gráficas:
líneas, rectángulos, óvalos, arcos etc. para graficar dentro de la misma.

Problema:
Confeccionar un programa que cree un objeto de la clase Canvas y muestre la
funcionalidad de las principales primitivas gráficas.
La interfaz visual debe ser similar a esta:

Programa: ejercicio254.py
Ver video

import tkinter as tk

class Aplicacion:
def __init__(self):
self.ventana1=tk.Tk()
self.canvas1=tk.Canvas(self.ventana1, wid
th=600, height=400, background="black")
self.canvas1.grid(column=0, row=0)
self.canvas1.create_line(0, 0, 100,50, fi
ll="white")
self.canvas1.create_rectangle(150,10, 250
,110, fill="white")
self.canvas1.create_oval(300,10,400,150,
fill="red")
self.canvas1.create_arc(420,10,550,110, f
ill="yellow", start=180, extent=90)
self.canvas1.create_rectangle(150,210, 25
0,310, outline="white")
self.canvas1.create_oval(300,210,400,350,
outline="red")
self.canvas1.create_arc(420,210,550,310,
outline="yellow", start=180, extent=90)
self.ventana1.mainloop()

aplicacion1=Aplicacion()
La clase Canvas se encuentra en el módulo 'tkinter':

import tkinter as tk

Creamos un objeto de la clase Canvas y le pasamos en el primer parámetro la


referencia a la ventana donde debe agregarse, los dos parámetros siguientes
son el ancho y el alto en píxeles, y finalmente el color de fondo de la
componente de tipo Canvas:
self.canvas1=tk.Canvas(self.ventana1, width=600, height=400, background=
"black")

Igual que cualquier otro Widget debemos ubicarlo mediante grid:

self.canvas1.grid(column=0, row=0)

Debemos hacer referencia a un sistema de ejes x e y. El punto (0,0) se


encuentra en el vértice superior izquierdo.
Para dibujar una línea la clase Canvas cuenta con el método 'create_line', El
primer y segundo parámetro representan la columna y fila donde se inicia la
línea (en nuestro ejemplo 0,0) y los otros dos valores representan la columna y
fila donde finaliza nuestra línea:

self.canvas1.create_line(0, 0, 100,50, fill="white")

Para dibujar un rectángulo debemos indicar dos puntos que se encuentren


dentro del control Canvas, los dos primeros valores indican el vértice superior
izquierdo y los dos siguientes el vértice inferior derecho:

self.canvas1.create_rectangle(150,10, 250,110, fill="white")

El rectángulo aparece con color relleno en blanco dado que pasamos el


parámetro fill con dicho valor.
Para dibujar un óvalo los parámetros son idénticos al método 'create_rectangle'
con la diferencia que en lugar de dibujar un rectángulo dibuja un óvalo
contenido en dicho rectángulo:

self.canvas1.create_oval(300,10,400,150, fill="red")

Para dibujar un trozo de tarta utilizamos el método 'create_arc', los primeros


parámetros son idénticos a los métodos 'create_rectangle' y 'create_oval'. El
parámetro start indica a partir de que grado debe comenzar el trozo de arco y
mediante el parámetro extent indicamos cuantos grados tiene el trozo de tarta:

self.canvas1.create_arc(420,10,550,110, fill="yellow", start=180, extent


=90)

Para que solo se pinte el perímetro de la figura no pasamos el parámetro fill y


pasamos solo el parámetro outline:

self.canvas1.create_rectangle(150,210, 250,310, outline="white")


self.canvas1.create_oval(300,210,400,350, outline="red")
self.canvas1.create_arc(420,210,550,310, outline="yellow", start=180, ex
tent=90)

Problema:
Crear una aplicación que solicite el ingreso de tres valores por teclado que
representan las cantidades de votos obtenidas por tres partidos políticos.
Luego mostrar un gráfico de barras horizontales.
La interfaz visual debe ser similar a esta:

Programa: ejercicio255.py
Ver video
import tkinter as tk
from tkinter import ttk

class Aplicacion:
def __init__(self):
self.ventana1=tk.Tk()
self.entradadatos()
self.canvas1=tk.Canvas(self.ventana1, wid
th=600, height=400, background="black")
self.canvas1.grid(column=0, row=1)
self.ventana1.mainloop()

def entradadatos(self):
self.lf1=ttk.LabelFrame(self.ventana1,tex
t="Partidos políticos")
self.lf1.grid(column=0, row=0, sticky="w"
)
self.label1=ttk.Label(self.lf1, text="Par
tido A:")
self.label1.grid(column=0,row=0, padx=5,
pady=5)
self.dato1=tk.StringVar()
self.entry1=ttk.Entry(self.lf1, textvaria
ble=self.dato1)
self.entry1.grid(column=1, row=0, padx=5,
pady=5)
self.label2=ttk.Label(self.lf1, text="Par
tido B:")
self.label2.grid(column=0,row=1, padx=5,
pady=5)
self.dato2=tk.StringVar()
self.entry2=ttk.Entry(self.lf1, textvaria
ble=self.dato2)
self.entry2.grid(column=1, row=1, padx=5,
pady=5)
self.label3=ttk.Label(self.lf1, text="Par
tido C:")
self.label3.grid(column=0,row=2, padx=5,
pady=5)
self.dato3=tk.StringVar()
self.entry3=ttk.Entry(self.lf1, textvaria
ble=self.dato3)
self.entry3.grid(column=1, row=2, padx=5,
pady=5)
self.boton1=ttk.Button(self.lf1, text="Ge
nerar gráfico", command=self.grafico_barra)
self.boton1.grid(column=0, row=3, columns
pan=2, padx=5, pady=5, sticky="we")
self.entry1.focus()

def grafico_barra(self):
self.canvas1.delete(tk.ALL)
valor1=int(self.dato1.get())
valor2=int(self.dato2.get())
valor3=int(self.dato3.get())
if valor1>valor2 and valor1>valor3:
mayor=valor1
else:
if valor2>valor3:
mayor=valor2
else:
mayor=valor3
largo1=valor1/mayor*400
largo2=valor2/mayor*400
largo3=valor3/mayor*400
self.canvas1.create_rectangle(10,10,10+la
rgo1,90,fill="red")
self.canvas1.create_rectangle(10,120,10+l
argo2,200,fill="blue")
self.canvas1.create_rectangle(10,230,10+l
argo3,310,fill="green")
self.canvas1.create_text(largo1+70, 50, t
ext="partido A", fill="white", font="Arial")
self.canvas1.create_text(largo2+70, 160,
text="partido B", fill="white", font="Arial")
self.canvas1.create_text(largo3+70, 270,
text="partido C", fill="white", font="Arial")

aplicacion1=Aplicacion()
En el método __init__ llamamos al método 'entradadatos' que crea el
LabelFrame con los 3 controles Entry, 3 controles Label y el botón:

def __init__(self):
self.ventana1=tk.Tk()
self.entradadatos()
self.canvas1=tk.Canvas(self.ventana1, width=600, height=400, background=
"black")
self.canvas1.grid(column=0, row=1)
self.ventana1.mainloop()

También creamos el objeto 'canvas1' y lo ubicamos en la segunda fila.


Cuando se presiona el botón "Generar gráfico" se ejecuta el método
'grafico_barra' donde lo primero que hacemos es borrar el contenido del control
de tipo Canvas:

self.canvas1.delete(tk.ALL)

Recuperamos los tres valores ingresados en los controles Entry y obtenemos el


mayor de ellos:

valor1=int(self.dato1.get())
valor2=int(self.dato2.get())
valor3=int(self.dato3.get())
if valor1>valor2 and valor1>valor3:
mayor=valor1
else:
if valor2>valor3:
mayor=valor2
else:
mayor=valor3

La ecuación para obtener el largo de la barra será:

largo=votos del partido/votos del partido con mas votos * 400 píxeles.

Entonces los largos de las tres barras se calculan:

largo1=valor1/mayor*400
largo2=valor2/mayor*400
largo3=valor3/mayor*400

Dibujamos las tres barras:

self.canvas1.create_rectangle(10,10,10+largo1,90,fill="red")
self.canvas1.create_rectangle(10,120,10+largo2,200,fill="blue")
self.canvas1.create_rectangle(10,230,10+largo3,310,fill="green")
Imprimimos un texto dentro del control Canvas mediante la primitiva
'create_text':

self.canvas1.create_text(largo1+70, 50, text="partido A", fill="white",


font="Arial")
self.canvas1.create_text(largo2+70, 160, text="partido B", fill="white",
font="Arial")
self.canvas1.create_text(largo3+70, 270, text="partido C", fill="white",
font="Arial")

Problema:
Crear una aplicación que solicite el ingreso de tres valores por teclado que
representan las cantidades de votos obtenidas por tres partidos políticos.
Luego mostrar un gráfico de tartas:.
La interfaz visual debe ser similar a esta:
Programa: ejercicio256.py
Ver video

import tkinter as tk
from tkinter import ttk

class Aplicacion:
def __init__(self):
self.ventana1=tk.Tk()
self.entradadatos()
self.canvas1=tk.Canvas(self.ventana1, wid
th=600, height=400, background="black")
self.canvas1.grid(column=0, row=1)
self.ventana1.mainloop()

def entradadatos(self):
self.lf1=ttk.LabelFrame(self.ventana1,tex
t="Partidos políticos")
self.lf1.grid(column=0, row=0, sticky="w"
)
self.label1=ttk.Label(self.lf1, text="Par
tido A:")
self.label1.grid(column=0,row=0, padx=5,
pady=5)
self.dato1=tk.StringVar()
self.entry1=ttk.Entry(self.lf1, textvaria
ble=self.dato1)
self.entry1.grid(column=1, row=0, padx=5,
pady=5)
self.label2=ttk.Label(self.lf1, text="Par
tido B:")
self.label2.grid(column=0,row=1, padx=5,
pady=5)
self.dato2=tk.StringVar()
self.entry2=ttk.Entry(self.lf1, textvaria
ble=self.dato2)
self.entry2.grid(column=1, row=1, padx=5,
pady=5)
self.label3=ttk.Label(self.lf1, text="Par
tido C:")
self.label3.grid(column=0,row=2, padx=5,
pady=5)
self.dato3=tk.StringVar()
self.entry3=ttk.Entry(self.lf1, textvaria
ble=self.dato3)
self.entry3.grid(column=1, row=2, padx=5,
pady=5)
self.boton1=ttk.Button(self.lf1, text="Ge
nerar gráfico", command=self.grafico_tarta)
self.boton1.grid(column=0, row=3, columns
pan=2, padx=5, pady=5, sticky="we")
self.entry1.focus()

def grafico_tarta(self):
self.canvas1.delete(tk.ALL)
valor1=int(self.dato1.get())
valor2=int(self.dato2.get())
valor3=int(self.dato3.get())
suma=valor1+valor2+valor3
grados1=valor1/suma*360
grados2=valor2/suma*360
grados3=valor3/suma*360
self.canvas1.create_arc(10,10,400,400,fil
l="red", start=0, extent=grados1)
self.canvas1.create_arc(10,10,400,400,fil
l="blue", start=grados1, extent=grados2)
self.canvas1.create_arc(10,10,400,400,fil
l="yellow", start=grados1+grados2, extent=grados3
)
self.canvas1.create_text(500, 50, text="p
artido A:"+str(valor1), fill="red", font="Arial")
self.canvas1.create_text(500, 100, text="
partido B:"+str(valor2), fill="blue", font="Arial
")
self.canvas1.create_text(500, 150, text="
partido C:"+str(valor3), fill="yellow", font="Ari
al")

aplicacion1=Aplicacion()
En el método grafico_tarta lo primero que hacemos es borrar el contenido del
control Canvas:

def grafico_tarta(self):
self.canvas1.delete(tk.ALL)

Extraemos los tres valores ingresados en los controles Entry:

valor1=int(self.dato1.get())
valor2=int(self.dato2.get())
valor3=int(self.dato3.get())

Sumamos la cantidad total de votos de los tres partidos:

suma=valor1+valor2+valor3

Seguidamente calculamos los grados que le corresponde a cada trozo de tarta


(teniendo en cuenta que tenemos 360 grados para repartir), Cada trozo de
tarta lo obtenemos mediante la ecuación:

tamaño trozo= cantidad de votos del partido / total de votos * 360

Los tres trozos se calculan con:


grados1=valor1/suma*360
grados2=valor2/suma*360
grados3=valor3/suma*360

Graficamos los tres trozos de tarta mediante la primitiva 'create_arc':

self.canvas1.create_arc(10,10,400,400,fill="red", start=0, extent=grados


1)
self.canvas1.create_arc(10,10,400,400,fill="blue", start=grados1, extent
=grados2)
self.canvas1.create_arc(10,10,400,400,fill="yellow", start=grados1+grado
s2, extent=grados3)

Finalmente mostramos las leyendas de los partidos junto con la cantidad de


votos dentro del control Canvas:

self.canvas1.create_text(500, 50, text="partido A:"+str(valor1), fill="r


ed", font="Arial")
self.canvas1.create_text(500, 100, text="partido B:"+str(valor2), fill="
blue", font="Arial")
self.canvas1.create_text(500, 150, text="partido C:"+str(valor3), fill="
yellow", font="Arial")

Problema propuesto
• Implementar un gráfico estadístico de tipo "Barra Porcentual":

Ver video
Solución

Retornar
74 - Canvas : captura de eventos del
mouse
Una actividad muy común es poder detectar cuando hemos presionado el
mouse dentro de un control Canvas (o de cualquier otro Widget que hayamos
visto) y a partir de eso disparar un evento.
Veremos con una serie de ejemplos la posibilidades de tkinter nos provee.

Problema:
Confeccionar un programa que cree un objeto de la clase Canvas y nos
muestre en el título de la ventana la coordenada actual del mouse dentro del
control Canvas y al presionar el botón izquierdo del mouse se dibuje un círculo
en dicha posición.
La interfaz visual debe ser similar a esta:

Programa: ejercicio258.py
Ver video
import tkinter as tk

class Aplicacion:
def __init__(self):
self.ventana1=tk.Tk()
self.canvas1=tk.Canvas(self.ventana1, wid
th=600, height=400, background="black")
self.canvas1.bind("<Motion>", self.mover_
mouse)
self.canvas1.bind("<Button-1>", self.pres
ion_mouse)
self.canvas1.grid(column=0, row=1)
self.ventana1.mainloop()

def presion_mouse(self, evento):


self.canvas1.create_oval(evento.x-5,event
o.y-5,evento.x+5,evento.y+5, fill="red")

def mover_mouse(self, evento):


self.ventana1.title(str(evento.x)+"-"+str
(evento.y))

aplicacion1=Aplicacion()
Luego de crear el objeto de la clase Canvas procedemos a llamar al método
bind e indicar el nombre de evento a capturar y el método que lo capturará:

self.canvas1=tk.Canvas(self.ventana1, width=600, height=400, background=


"black")
self.canvas1.bind("<Motion>", self.mover_mouse)
self.canvas1.bind("<Button-1>", self.presion_mouse)
Para capturar el desplazamiento de la flecha del mouse debemos especificar
'Motion' y la presión del botón izquierdo del mouse debemos especificar
''Button-1'.
Cada vez que se produce un desplazamiento de la flecha del mouse dentro de
la componente canvas1 se ejecuta el método 'mover_mouse':

def mover_mouse(self, evento):


self.ventana1.title(str(evento.x)+"-"+str(evento.y))

Todos los métodos que capturan eventos reciben un parámetro con


información del evento propiamente dicho. Los atributos x e y almacenan la
coordenada actual de la flecha del mouse.
El método 'presion_mouse' se dispara cuando presionamos el botón izquierdo
del mouse dentro del objeto canvas1. Dibujamos un círculo teniendo en cuenta
donde se encuentra la flecha del mouse en este momento:

def presion_mouse(self, evento):


self.canvas1.create_oval(evento.x-5,evento.y-5,evento.x+5,evento.y+5, fi
ll="red")

Acotaciones
La diversidad de eventos que podemos capturar es muy grande, veamos
algunos ejemplos:

• Para capturar el evento clic del botón izquierdo del mouse indicamos en
el método bind <Button-1>, el botón central <Button-2> y el botón
derecho del mouse <Button-3>

• Si necesitamos capturar el evento clic del botón derecho del mouse y a


su vez que se encuentre presionada la tecla Shift tenemos que codificar:

• self.canvas1.bind("<Shift Button-1>", self.presion_mouse)

En lugar de Shift podemos verificar si se está presionando la tecla


control:

self.canvas1.bind("<Control Button-1>", self.presion_mouse)

Inclusive detectar el evento si se presiona Shift, Control y el botón


izquierdo del mouse:

self.canvas1.bind("<Control Shift Button-1>", self.presion_mouse)


La tecla Alt, Shift, Control y el botón izquierdo del mouse:

self.canvas1.bind("<Control Shift Alt Button-1>", self.presion_mo


use)

• Si necesitamos hacer algo cuando la flecha del mouse entra al control


podemos plantear la captura del evento:

self.canvas1.bind("<Enter>", self.entrada)

Y si queremos detectar cuando la flecha del mouse sale de la


componente:

self.canvas1.bind("<Leave>", self.salida)

• Para detectar el doble clic de un botón del mouse:

• self.canvas1.bind("<Double-Button-1>", self.presion_mouse)

Problema:
Confeccionar un programa que cree un objeto de la clase Canvas y nos
permita dibujar a mano alzada dentro del mismo.
La interfaz visual debe ser similar a esta luego de dibujar unos trazos:
Programa: ejercicio259.py
Ver video

import tkinter as tk

class Aplicacion:

def __init__(self):
self.ventana1=tk.Tk()
self.canvas1=tk.Canvas(self.ventana1, wid
th=600, height=400, background="black")
self.canvas1.grid(column=0,row=0)
self.canvas1.bind("<ButtonPress-1>",self.
boton_presion)
self.canvas1.bind("<Motion>", self.mover_
mouse)
self.canvas1.bind("<ButtonRelease-1>",sel
f.boton_soltar)
self.presionado=False
self.ventana1.mainloop()

def boton_presion(self, evento):


self.presionado=True
self.origenx=evento.x
self.origeny=evento.y

def mover_mouse(self, evento):


if self.presionado:
self.canvas1.create_line(self.origenx
,self.origeny,evento.x,evento.y, fill="red")
self.origenx=evento.x
self.origeny=evento.y

def boton_soltar(self,evento):
self.presionado=False

aplicacion1=Aplicacion()
Para poder dibujar a mano alzada vamos a identificar los eventos cuando se
presiona el botón izquierdo del mouse:

self.canvas1.bind("<ButtonPress-1>", self.boton_presion)

Cuando se mueve el mouse dentro del control Canvas:


self.canvas1.bind("<Motion>", self.mover_mouse)

Y cuando se suelta el botón izquierdo del mouse:

self.canvas1.bind("<ButtonRelease-1>", self.boton_soltar)

Cuando se presiona el botón izquierdo del mouse se cambia el estado de la


bandera 'presionado' y se definen los atributos origenx y origeny con la
coordenada actual de la flecha del mouse:

def boton_presion(self, evento):


self.presionado=True
self.origenx=evento.x
self.origeny=evento.y

Cada vez que se produce un desplazamiento de la flecha del mouse si la


bandera 'presionado' tiene un valor 'True' se pasa a dibujar una línea desde la
coordenada donde se encontraba la flecha del mouse cuando se lo presionó y
la nueva coordenada, también actualizamos la coordenada origenx y origeny
con la nueva posición:

def mover_mouse(self, evento):


if self.presionado:
self.canvas1.create_line(self.origenx,self.origeny,evento.x,evento.y
, fill="red")
self.origenx=evento.x
self.origeny=evento.y

El método boton_soltar se ejecuta cuando el operador deja de presionar el


botón izquierdo del mouse, donde volvemos a disponer el atributo 'presionado'
con el valor 'False', lo que hace que cuando se mueve la flecha del mouse no
se dibuje la línea:

def boton_soltar(self,evento):
self.presionado=False

Retornar
75 - Canvas : borrar figuras mediante
Ids y Tags
Cuando creamos una figura con los métodos que provee la clase Canvas, el
mismo nos retorna un Id (identificador) de dicha figura. Luego podemos hacer
referencia a la misma mediante ese Id.
Podemos asociar además a una o más figuras un Tag (marca) y luego borrar
todas las figuras que tienen dicho Tag.

Problema:
Confeccionar un programa que cree un objeto de la clase Canvas y luego
dibuje una línea, un réctángulo y un óvalo, almacenar el Id de cada dibujo en
un atributo.
Crear también 3 cuadrados y definir el parámetro tag con el mismo valor para
cada uno de ellos.
Mediante cinco botones permitir: borrar la línea, borrar el rectángulo, borrar el
óvalo, borrar todos los cuadrados y borrar todas las figuras contenidas en el
objeto Canvas.
La interfaz visual debe ser similar a esta:
Programa: ejercicio260.py
Ver video

import tkinter as tk
from tkinter import ttk

class Aplicacion:
def __init__(self):
self.ventana1=tk.Tk()
self.crear_botones()
self.canvas1=tk.Canvas(self.ventana1, wid
th=600, height=400, background="black")
self.canvas1.grid(column=0, row=1)
self.linea=self.canvas1.create_line(0, 0,
100,50, fill="white")
self.rectangulo=self.canvas1.create_recta
ngle(150,10, 300,110, fill="white")
self.ovalo=self.canvas1.create_oval(400,1
0,500,150, fill="red")
self.canvas1.create_rectangle(100,300,150
,350,fill="#aaaaaa", tag="cuadrado")
self.canvas1.create_rectangle(200,300,250
,350,fill="#555555", tag="cuadrado")
self.canvas1.create_rectangle(300,300,350
,350,fill="#cccccc", tag="cuadrado")
self.ventana1.mainloop()

def crear_botones(self):
self.labelframe1=ttk.LabelFrame(self.vent
ana1,text="opciones")
self.labelframe1.grid(column=0, row=0, st
icky="w", padx=5, pady=5)
self.boton1=ttk.Button(self.labelframe1,
text="borrar linea", command=self.borrar_linea)
self.boton1.grid(column=0, row=0, padx=5)
self.boton2=ttk.Button(self.labelframe1,
text="borrar rectángulo", command=self.borrar_rec
tangulo)
self.boton2.grid(column=1, row=0, padx=5)
self.boton3=ttk.Button(self.labelframe1,
text="borrar óvalo", command=self.borrar_ovalo)
self.boton3.grid(column=2, row=0, padx=5)
self.boton4=ttk.Button(self.labelframe1,
text="borrar todos los cuadrados", command=self.b
orrar_cuadrados)
self.boton4.grid(column=3, row=0, padx=5)
self.boton5=ttk.Button(self.labelframe1,
text="borrar todos", command=self.borrar_todos)
self.boton5.grid(column=4, row=0, padx=5)

def borrar_linea(self):
self.canvas1.delete(self.linea)

def borrar_rectangulo(self):
self.canvas1.delete(self.rectangulo)

def borrar_ovalo(self):
self.canvas1.delete(self.ovalo)

def borrar_cuadrados(self):
self.canvas1.delete("cuadrado")

def borrar_todos(self):
self.canvas1.delete(tk.ALL)

aplicacion1=Aplicacion()
Las tres primeras figuras que creamos almacenamos en atributos de la clase la
referencia a las mismas:

self.linea=self.canvas1.create_line(0, 0, 100,50, fill="white")


self.rectangulo=self.canvas1.create_rectangle(150,10, 300,110, fill="whi
te")
self.ovalo=self.canvas1.create_oval(400,10,500,150, fill="red")

Los tres cuadrados que creamos definimos el parámetro tag con el string
"cuadrado":

self.canvas1.create_rectangle(100,300,150,350,fill="#aaaaaa", tag="cuadr
ado")
self.canvas1.create_rectangle(200,300,250,350,fill="#555555", tag="cuadr
ado")
self.canvas1.create_rectangle(300,300,350,350,fill="#cccccc", tag="cuadr
ado")

El método 'crear_botones' tiene solo el objetivo de crear los 5 botones que


necesita la aplicación y los agrupa en un LabelFrame.
Cuando se presiona el botón de borrar la línea se llama al método delete de la
clase Canvas pasando el atributo que almacena la referencia a la línea creada:

def borrar_linea(self):
self.canvas1.delete(self.linea)

De forma similar se procede a borrar el rectángulo y el óvalo mediante la


referencia del Id:

def borrar_rectangulo(self):
self.canvas1.delete(self.rectangulo)

def borrar_ovalo(self):
self.canvas1.delete(self.ovalo)

Para eliminar todos los cuadrados también llamamos al método delete y le


pasamos el string que almacenamos en su tag:

def borrar_cuadrados(self):
self.canvas1.delete("cuadrado")

Finalmente para borrar todos las figuras que tiene un control Canvas debemos
llamar a delete y pasar la variable ALL que define el módulo tkinter:

def borrar_todos(self):
self.canvas1.delete(tk.ALL)
Acotaciones
Cuando trabajamos con el editor Visual Studio Code podemos navegar la
referencia de variables, métodos, clases etc. presionando la tecla Control y
posicionando la flecha del mouse sobre el identificar:

Si hacemos clic luego que aparece subrayado se abre el archivo que contiene
dicha
definición:

Esta posibilidad de navegar el código fuente de los módulos nos puede facilitar
entender su funcionamiento. Según lo visto la variable ALL del módulo tkinter
almacena la cadena 'all', luego podemos escribir la eliminación de todos los
gráficos con la sintaxis:

def borrar_todos(self):
self.canvas1.delete('all')

Retornar

76 - Canvas : desplazar una figura


mediante el método move
Otra situación donde tiene sentido almacenar el Id de una figura es cuando en
un momento posterior queremos desplazarla a otra posición dentro del objeto
Canvas.
Problema:
Confeccionar un programa que que muestre un cuadrado dentro de un Canvas.
Cuando se presione alguna de las teclas de flecha proceder a desplazar la
figura 4 píxeles teniendo en cuenta la dirección de la tecla de flecha
presionada.
La interfaz visual debe ser similar a esta:

Programa: ejercicio261.py
Ver video

import tkinter as tk

class Aplicacion:
def __init__(self):
self.ventana1=tk.Tk()
self.canvas1=tk.Canvas(self.ventana1, wid
th=600, height=400, background="black")
self.canvas1.grid(column=0, row=0)
self.cuadrado=self.canvas1.create_rectang
le(150,10,200,60, fill="red")
self.ventana1.bind("<KeyPress>", self.pre
sion_tecla)
self.ventana1.mainloop()

def presion_tecla(self, evento):


if evento.keysym=='Right':
self.canvas1.move(self.cuadrado, 4, 0
)
if evento.keysym=='Left':
self.canvas1.move(self.cuadrado, -4,
0)
if evento.keysym=='Down':
self.canvas1.move(self.cuadrado, 0, 4
)
if evento.keysym=='Up':
self.canvas1.move(self.cuadrado, 0, -
4)

aplicacion1=Aplicacion()
Creamos un objeto de la clase Canvas de 600 píxeles de ancho por 400 de
alto:

self.canvas1=tk.Canvas(self.ventana1, width=600, height=400, background=


"black")
self.canvas1.grid(column=0, row=0)

Creamos un cuadrado de color rojo y guardamos su referencia en el atributo


'cuadrado':

self.cuadrado=self.canvas1.create_rectangle(150,10,200,60, fill="red")

Ponemos a escuchar el evento 'KeyPress' e indicamos el método a ejecutar en


caso que se dispare:

self.ventana1.bind("<KeyPress>", self.presion_tecla)

En el método 'presion_tecla' verificamos cual de las cuatro teclas de flecha se


ha presionado y llamamos al método 'move' de la clase Canvas, debemos
pasar la referencia de la figura y cuantos píxeles se debe desplazar en 'x' e 'y':

def presion_tecla(self, evento):


if evento.keysym=='Right':
self.canvas1.move(self.cuadrado, 4, 0)
if evento.keysym=='Left':
self.canvas1.move(self.cuadrado, -4, 0)
if evento.keysym=='Down':
self.canvas1.move(self.cuadrado, 0, 4)
if evento.keysym=='Up':
self.canvas1.move(self.cuadrado, 0, -4)

Problema propuesto
• Modificar el problema que desplaza un cuadrado con las teclas de
flechas de tal modo que la figura no pueda salir del espacio definido para
el Canvas.
Para saber la posición actual de una figura la clase Canvas cuenta con
el método 'coords':

• x1, y1, x2, y2 = self.canvas1.coords(self.cuadrado)

Ver video
Solución
Retornar

77 - Canvas : mostrar una imagen


Si necesitamos mostrar una imagen dentro de una componente de tipo Canvas
disponemos del método 'PhotoImage' que se encuentra en el módulo tkinter
para su lectura, y luego mediante el método 'create_image' de la clase Canvas
para su visualización.

Problema:
Se cuenta con tres archivos de tipo png con las imágenes de distintas cartas.
Mostrarlas a cada una dentro de una componente de tipo Canvas.
Puede descargar estas tres imágenes y copiarlas en la carpeta donde codifica
sus programas en Python:

La interfaz visual debe ser similar a esta:


Programa: ejercicio263.py
Ver video

import tkinter as tk

class Aplicacion:
def __init__(self):
self.ventana1=tk.Tk()
self.canvas1=tk.Canvas(self.ventana1, wid
th=700, height=500, background="black")
self.canvas1.grid(column=0, row=0)
archi1=tk.PhotoImage(file="carta1.png")
self.canvas1.create_image(30, 100, image=
archi1, anchor="nw")
archi2=tk.PhotoImage(file="carta2.png")
self.canvas1.create_image(240, 100, image
=archi2, anchor="nw")
archi3=tk.PhotoImage(file="carta3.png")
self.canvas1.create_image(450, 100, image
=archi3, anchor="nw")
self.ventana1.mainloop()

aplicacion1=Aplicacion()
Creamos una componente Canvas de 700 píxeles de ancho por 500 píxeles de
alto, sabiendo que los archivos de las cartas tienen un tamaño de 200*300
píxeles:

self.canvas1=tk.Canvas(self.ventana1, width=700, height=500, background=


"black")

Creamos un objeto de la clase PhotoImage y le pasamos como parámetro el


nombre del archivo a leer del disco duro (el archivo 'carta1.png' se debe
encontrar en la misma carpeta que nuestro programa de Python, sino debemos
indicar el path):

archi1=tk.PhotoImage(file="carta1.png")

Seguidamente llamamos al método 'create_image' de la clase Canvas y le


pasamos la columna y la fila donde debe mostrarse la imagen, en el parámetro
image le pasamos la referencia del archivo que acabamos de leer:

self.canvas1.create_image(30, 100, image=archi1, anchor="nw")

El parámetro anchor es importante que lo inicialicemos con el valor "nw" (north,


west) para que el vértice superior izquierdo se muestre en la coordenada
(30,100)
Por defecto el parámetro anchor tiene el valor "center".
Los valores posibles del parámetro anchor son: "n", "ne", "e", "se", "s", "sw",
"w", "nw" y "center"
Los mismos pasos hacemos para la lectura y muestra de las otras dos
imágenes:

archi2=tk.PhotoImage(file="carta2.png")
self.canvas1.create_image(240, 100, image=archi2, anchor="nw")
archi3=tk.PhotoImage(file="carta3.png")
self.canvas1.create_image(450, 100, image=archi3, anchor="nw")

Acotaciones
Los formatos reconocidos de la clase PhotoImage son: GIF, PNG, PGM y PPM.
Si el archivo se encuentra en otra carpeta debemos indicar el path del mismo:

archi1=tk.PhotoImage(file="C:/programaspython/carta1.png")

Problema propuesto
• Disponer un botón y mostrar al azar una de las tres cartas del problema
anterior. Cada vez que se presione el botón generar un valor aleatorio y
a partir de dicho valor mostrar una carta.
Ver video
Solución

Retornar

78 - Canvas : mover una figura


Otro algoritmo útil cuando trabajamos con figuras dentro de un control Canvas
es la posibilidad de arrastrar y soltar figuras.
Debemos capturar los eventos cuando se hace clic dentro de una figura y
luego cada vez que se desplaza la flecha del mouse.

Problema:
Se cuenta con dos archivos de tipo png con las imágenes de distintas cartas.
Mostrarlas a cada una dentro de una componente de tipo Canvas y permitir
moverlas dentro del control mediante el mouse.
Puede descargar estas dos imágenes y copiarlas en la carpeta donde codifica
sus programas en Python:

La interfaz visual debe ser similar a esta luego de mover con el mouse las
imágenes:
Programa: ejercicio265.py
Ver video

import tkinter as tk

class Aplicacion:
def __init__(self):
self.ventana1=tk.Tk()
self.canvas1=tk.Canvas(self.ventana1, wid
th=900, height=500, background="black")
self.canvas1.grid(column=0, row=0)
archi1=tk.PhotoImage(file="carta1.png")
self.canvas1.create_image(30, 100, image=
archi1, anchor="nw", tags="movil")
archi2=tk.PhotoImage(file="carta2.png")
self.canvas1.create_image(400, 100, image
=archi2, anchor="nw", tags="movil")
self.canvas1.tag_bind("movil", "<ButtonPr
ess-1>", self.presion_boton)
self.canvas1.tag_bind("movil", "<Button1-
Motion>", self.mover)
self.carta_seleccionada = None
self.ventana1.mainloop()

def presion_boton(self, evento):


carta = self.canvas1.find_withtag(tk.CURR
ENT)
self.carta_seleccionada = (carta, evento.
x, evento.y)
def mover(self, evento):
x, y = evento.x, evento.y
carta, x1, y1 = self.carta_seleccionada
self.canvas1.move(carta, x - x1, y - y1)
self.carta_seleccionada = (carta, x, y)

aplicacion1=Aplicacion()
Creamos primero el control de tipo Canvas y las dos imágenes respectivas. A
cada una de las imágenes iniciamos el parámetro 'tags' con un valor:

self.canvas1=tk.Canvas(self.ventana1, width=900, height=500, background=


"black")
self.canvas1.grid(column=0, row=0)
archi1=tk.PhotoImage(file="carta1.png")
self.canvas1.create_image(30, 100, image=archi1, anchor="nw", tags="movi
l")
archi2=tk.PhotoImage(file="carta2.png")
self.canvas1.create_image(400, 100, image=archi2, anchor="nw", tags="mov
il")

Mediante el método 'tag_bind' de la clase Canvas enlazamos el evento de


presión del botón izquierdo para todas las figuras que tienen el tag con el valor
'movil':

self.canvas1.tag_bind("movil", "<ButtonPress-1>", self.presion_boton)

De forma idéntica hacemos la captura del desplazamiento del mouse:

self.canvas1.tag_bind("movil", "<Button1-Motion>", self.mover)

Inicializamos el atributo 'carta_seleccionada' con el valor None, indicando que


ninguna de las cartas se ha hecho clic sobre la misma:

self.carta_seleccionada = None

Cuando se presiona el botón izquierdo sobre alguna de las cartas se extrae


mediante el método 'find_withtag' la referencia de la carta presionada y se
guarda en el atributo 'carta_seleccionada' una tupla que contiene la carta que
se acaba de presionar y la coordenada x e y actual:

def presion_boton(self, evento):


carta = self.canvas1.find_withtag(tk.CURRENT)
self.carta_seleccionada = (carta, evento.x, evento.y)

Cuando se mueve la flecha del mouse extraemos del atributo


'carta_seleccionada' la carta que se había presionado y su coordenada,
procedemos a desplazarla mediante el método 'move' y guardamos la nueva
posición de la carta:

def mover(self, evento):


x, y = evento.x, evento.y
carta, x1, y1 = self.carta_seleccionada
self.canvas1.move(carta, x - x1, y - y1)
self.carta_seleccionada = (carta, x, y)

Problema propuesto
• Crear 100 cuadrados de color rojo y disponerlos en el control Canvas en
posiciones aleatorias. Permitir desplazar con el mouse cualquiera de los
cuadrados.
Ver video
Solución

Retornar

79 - Archivos de texto: creación,


escritura y lectura
Una actividad muy común en un programa es el almacenamiento y
recuperación de datos almacenado en un dispositivo secundario (disco duro).
Existen muchos modos de almacenar datos como son los archivos de texto,
archivos binarios, bases de datos etc.
Veremos en este concepto como almacenar y recuperar datos de un archivo de
texto.

Archivo de texto
Un archivo de texto contiene un conjunto de caracteres estructurados en
distintas líneas. Es un formato de archivo ampliamente utilizado como pueden
ser:

• El código fuente de un script en Python se almacena en un archivo de


texto (igual que cualquier otro lenguaje de programación)

• Archivos HTML, CSS, XML se almacenan en archivos de texto.

• Archivos JSON etc.

Creación de un archivo de texto y almacenamiento de


datos.
Como es una actividad tan común en todo programa el lenguaje Python incluye
por defecto todas las funcionalidades para trabajar con archivos de texto.
Veamos con un ejemplo como crear y almacenar caracteres en un archivo de
texto.

Problema:
Crear un archivo de texto llamado 'datos.txt', almacenar tres líneas de texto.
Abrir luego el archivo creado con un editor de texto.
Programa: ejercicio267.py
Ver video

archi1=open("datos.txt","w")
archi1.write("Primer línea.\n")
archi1.write("Segunda línea.\n")
archi1.write("Tercer línea.\n")
archi1.close()
Luego de ejecutar este programa (no muestra nada por pantalla) debemos
abrir con un editor de texto el archivo de texto que se acaba de crear llamado
'datos.txt':
Para crear un archivo de texto debemos llamar a la función open y pasar dos
parámetros, el primero indica el nombre del archivo a crear y el segundo un
string con el caracter "w" (la "w" write indica crear el archivo de texto):

archi1=open("datos.txt","w")

Si el archivo 'datos.txt' ya existe luego se crea uno nuevo y se borra el actual.


El archivo se crea en la misma carpeta donde se está ejecutando el script de
Python, si necesitamos que se cree en otra carpeta podemos indicar el path del
mismo:

archi1 = open("c:/administracion/datos.txt","w")

Si indicamos un path inexistente se genera un error.


Para grabar caracteres en el archivo de texto utilizamos el método 'write' y le
pasamos un string a grabar:

archi1.write("Primer línea.\n")

Mediante la sintaxis \n indicamos que debe almacenarse un salto de línea en el


archivo de texto.
Si no incluimos los respectivos \n:

archi1.write("Primer línea.")
archi1.write("Segunda línea.")
archi1.write("Tercer línea.")

El archivo de texto tiene una sola línea:


Luego de trabajar con el archivo de texto debemos liberarlo para que otro
programa pueda acceder a su contenido:

archi1.close()

Lectura de un archivo de texto.


Ver video

Problema:
Leer el contenido del archivo de texto 'datos.txt'.
Programa: ejercicio268.py

archi1=open("datos.txt","r")
contenido=archi1.read()
print(contenido)
archi1.close()
Luego de ejecutar este programa:
Llamamos a la función 'open' y le pasamos el nombre del archivo a leer y un
string con el caracter "r" (read):

archi1=open("datos.txt","r")

El método 'read' recupera todas las líneas del archivo de texto (recupera el
archivo completo):

contenido=archi1.read()

Luego de trabajar con el archivo de texto debemos liberarlo para que otro
programa pueda acceder a su contenido:

archi1.close()

El método 'read' sin parámetros retorna todos los caracteres almacenados en


el archivo, opcionalmente podemos pasar un entero que represente la cantidad
de caracteres a leer:

archi1=open("datos.txt","r")
contenido=archi1.read(6)
print(contenido) # imprime: Primer
archi1.close()

Lectura de un archivo de texto línea a línea.


En algunas situaciones podemos necesitar leer el contenido de un archivo de
texto línea a línea. Disponemos de un método llamado 'readline' que lee una
línea completa del archivo, inclusive retorna el caracter '\n' de fin de línea.

Problema:
Leer el contenido del archivo de texto 'datos.txt' línea a línea.
Programa: ejercicio269.py

archi1=open("datos.txt","r")
linea=archi1.readline()
while linea!='':
print(linea, end='')
linea=archi1.readline()
archi1.close()
Antes de la estructura repetitiva 'while' leemos la primer lína del archivo de
texto:

linea=archi1.readline()

Luego mientras la variable 'linea' sea distinta a un string vacío imprimimos el


contenido de la variable 'linea' evitando que genere un salto de línea la función
print mediante la asignación del parámetro end con el valor de '':

while linea!='':
print(linea, end='')
linea=archi1.readline()

También dentro de la estructura while leemos las siguientes líneas.


Podemos recorrer el archivo leyendo línea a línea utilizando la estructura
repetitiva for:
Programa: ejercicio270.py

archi1=open("datos.txt","r")
for linea in archi1:
print(linea, end='')
archi1.close()
Es una forma más compacta de recorrer cada una de las líneas del archivo de
texto.

Almacenar un archivo de texto en una lista


Ver video
Mediante el método 'readlines' podemos recuperar cada una de las líneas del
archivo de texto y almacenarlas en una lista.

Problema:
Leer el contenido del archivo de texto 'datos.txt' y almacenar sus líneas en una
lista. Imprimir la cantidad de líneas que tiene el archivo y su contenido.
Programa: ejercicio271.py

archi1=open("datos.txt","r")
lineas=archi1.readlines()
print('El archivo tiene', len(lineas), 'líneas')
print('El contenido del archivo')
for linea in lineas:
print(linea, end='')
archi1.close()
Mediante la llamada al método 'readlines' obtenemos una lista con todas las
líneas del archivo 'datos.txt':

lineas=archi1.readlines()

Imprimimos seguidamente la cantidad de elementos de la lista que coincide


con la cantidad de líneas que tiene el archivo de texto:
print('El archivo tiene', len(lineas), 'líneas')

Para imprimir el contenido del archivo de texto procedemos a imprimir la lista:

print('El contenido del archivo')


for linea in lineas:
print(linea, end='')

Una variante del método 'readlines' es pasar como un parámetro entero que
represente que línea queremos recuperar:

linea=archi1.readlines(2)
print(linea, end='') # imprime ['Primer línea.\n']

Abrir un archivo de texto para añadir líneas.


Hemos visto que cuando llamamos a la función 'open' el segundo parámetro
puede ser "w", "r" y si queremos que se abra para añadir sin borrar las líneas
actuales del archivo debemos hacerlo con el parámetro "a" (append).

Problema:
Abrir el archivo de texto 'datos.txt' y luego agregar 2 líneas. Imprimir luego el
archivo completo.
Programa: ejercicio272.py
Ver video

archi1=open("datos.txt","a")
archi1.write("nueva línea 1\n")
archi1.write("nueva línea 2\n")
archi1.close()
archi1=open("datos.txt","r")
contenido=archi1.read()
print(contenido)
archi1.close()
Abrimos el archivo 'datos.txt' en modo agregar:
archi1=open("datos.txt","a")

Almacenamos dos líneas en el archivo:

archi1.write("nueva línea 1\n")


archi1.write("nueva línea 2\n")

Cerramos el archivo y lo volvemos a abrir para leer su contenido:

archi1.close()
archi1=open("datos.txt","r")
contenido=archi1.read()
print(contenido)
archi1.close()

Abrir un archivo para leer y agregar datos.


Hay una cuarta forma de abrir un archivo indicando en el segundo parámetro
de la función open el string "r+", con dicha opción podemos leer y escribir.

Problema:
Abrir un archivo de texto con el parámetro "r+", imprimir su contenido actual y
agregar luego dos líneas al final.
Programa: ejercicio273.py

archi1=open("datos.txt","r+")
contenido=archi1.read()
print(contenido)
archi1.write("Otra línea 1\n")
archi1.write("Otra línea 2\n")
archi1.close()

Codificación de caracteres utf-8.


Actualmente se utiliza mucho la codificación de caracteres utf-8 la que nos
permite representar una infinidad de caracteres de distintos idiomas y
símbolos.
En Python debemos indicar cuando abrimos el archivo de texto mediante el
parámetro 'encoding' la codificación de caracteres utilizada.

Problema:
Crear un archivo de texto llamado 'datos.txt' con una codificación utf-8,
almacenar tres líneas de texto. Abrir luego el archivo creado con el editor VS
Code.
Programa: ejercicio274.py
Ver video

archi1=open("datos.txt","w", encoding="utf-8")
archi1.write("Primer línea.\n")
archi1.write("Segunda línea.\n")
archi1.write("Tercer línea.\n")
archi1.close()
Si ahora abrimos el archivo de texto creado con un editor que permite trabajar
con archivos con codificación utf-8 el resultado es:
Retornar

80 - Archivos de texto: interfaz visual


con tkinter para leer y escribir un
archivo
Conociendo como poder crear, leer y escribir en un archivo de texto, vamos a
combinarlo con los conceptos de la librería visual tkinter para implementar un
programa que nos permita escribir un texto y guardarlo en un archivo de texto.

Problema:
Confeccionar una interfaz visual que contenga un menú de opciones que
permitan "Guardar archivo", "Recuperar archivo" y "Salir del programa".
En la ventana principal debe aparecer un control de tipo 'scrolledtext' donde el
operador pueda escribir un texto para luego grabarlo en un archivo de texto.
También el control 'scrolledtext' debe cargarse con el contenido de un archivo
existente en el disco duro.
La interfaz visual debe ser:

Cuando se selecciona la opción "Guardar archivo" debe aparecer el diálogo


siguiente:

Y cuando se selecciona la opción "Recuperar archivo" debe aparecer el


diálogo:
Programa: ejercicio275.py
Ver video

import tkinter as tk
from tkinter import scrolledtext as st
import sys
from tkinter import filedialog as fd
from tkinter import messagebox as mb

class Aplicacion:
def __init__(self):
self.ventana1=tk.Tk()
self.agregar_menu()
self.scrolledtext1=st.ScrolledText(self.v
entana1, width=80, height=20)
self.scrolledtext1.grid(column=0,row=0, p
adx=10, pady=10)
self.ventana1.mainloop()

def agregar_menu(self):
menubar1 = tk.Menu(self.ventana1)
self.ventana1.config(menu=menubar1)
opciones1 = tk.Menu(menubar1, tearoff=0)
opciones1.add_command(label="Guardar arch
ivo", command=self.guardar)
opciones1.add_command(label="Recuperar ar
chivo", command=self.recuperar)
opciones1.add_separator()
opciones1.add_command(label="Salir", comm
and=self.salir)
menubar1.add_cascade(label="Archivo", men
u=opciones1)

def salir(self):
sys.exit()

def guardar(self):
nombrearch=fd.asksaveasfilename(initialdi
r = "/",title = "Guardar como",filetypes = (("txt
files","*.txt"),("todos los archivos","*.*")))
if nombrearch!='':
archi1=open(nombrearch, "w", encoding
="utf-8")
archi1.write(self.scrolledtext1.get("
1.0", tk.END))
archi1.close()
mb.showinfo("Información", "Los datos
fueron guardados en el archivo.")

def recuperar(self):
nombrearch=fd.askopenfilename(initialdir
= "/",title = "Seleccione archivo",filetypes = ((
"txt files","*.txt"),("todos los archivos","*.*")
))
if nombrearch!='':
archi1=open(nombrearch, "r", encoding
="utf-8")
contenido=archi1.read()
archi1.close()
self.scrolledtext1.delete("1.0", tk.E
ND)
self.scrolledtext1.insert("1.0", cont
enido)

aplicacion1=Aplicacion()
La parte de la interfaz visual la dividimos por un lado en la creación del
'ScrolledText':

self.scrolledtext1=st.ScrolledText(self.ventana1, width=80, height=20)


self.scrolledtext1.grid(column=0,row=0, padx=10, pady=10)
Y la creación del menú con las tres opciones, este método es llamado desde el
método __init__:

def agregar_menu(self):
menubar1 = tk.Menu(self.ventana1)
self.ventana1.config(menu=menubar1)
opciones1 = tk.Menu(menubar1, tearoff=0)
opciones1.add_command(label="Guardar archivo", command=self.guardar)
opciones1.add_command(label="Recuperar archivo", command=self.recuperar)
opciones1.add_separator()
opciones1.add_command(label="Salir", command=self.salir)
menubar1.add_cascade(label="Archivo", menu=opciones1)

Veamos ahora el algoritmo que nos permite almacenar el contenido del


'ScrolledText' en un archivo de texto. Esta actividad se lleva a cabo en el
método 'guardar' donde hacemos uso del módulo 'filedialog' que mediante la
llamada a la función 'asksaveasfilename' nos muestra un diálogo para ingresar
el nombre del archivo y el directorio donde almacenarlo:

def guardar(self):
nombrearch=fd.asksaveasfilename(initialdir = "/",title = "Guardar como",
filetypes = (("txt files","*.txt"),("todos los archivos","*.*")))

La función 'asksaveasfilename' retorna un string vacío si presionamos el botón


de cancelar en el diálogo, y en caso contrario retorna el path y nombre de
archivo. Procedemos a crear un archivo de texto y almacenar todo el contenido
del 'ScrolledText':

if nombrearch!='':
archi1=open(nombrearch, "w", encoding="utf-8")
archi1.write(self.scrolledtext1.get("1.0", tk.END))
archi1.close()
mb.showinfo("Información", "Los datos fueron guardados en el archivo
.")

La actividad de recuperar el contenido de un archivo de texto almacenado en el


disco duro se efectúa en el método 'recuperar'. Nuevamente hacemos uso del
módulo 'filedialog' llamando a la función 'askopenfilename' que nos retorna el
path y nombre de archivo que seleccionamos:
def recuperar(self):
nombrearch=fd.askopenfilename(initialdir = "/",title = "Seleccione archi
vo",filetypes = (("txt files","*.txt"),("todos los archivos","*.*")))

En el caso que se haya seleccionado un archivo del disco duro procedemos a


abrirlo y cargar su contenido en el 'ScrolledText':

if nombrearch!='':
archi1=open(nombrearch, "r", encoding="utf-8")
contenido=archi1.read()
archi1.close()
self.scrolledtext1.delete("1.0", tk.END)
self.scrolledtext1.insert("1.0", contenido)

Retornar

81 - MySQL : Base de datos desde


Python
Cuando tenemos que almacenar gran cantidad de datos y su posterior
procesamiento es muy común utilizar un gestor de bases de datos.
Con Python podemos comunicarnos con un gestor de bases de datos para
enviar y recuperar datos.
Existen gran cantidad de gestores de bases de datos y el primero que veremos
para ver cual es la mecánica para conectarnos desde Python será el gestor de
base de datos MySQL.
Deberemos instalar primero si no lo tenemos a MySQL.

Instalación de MySQL.
Para facilitar la administración del MySQL utilizaremos el programa XAMPP
que entre otros instala:

• MySQL
• PHPMyAdmin (que nos permitirá administrar las bases de datos
existentes en MySQL)

• PHP (Lenguaje que nos permite ejecutar el PHPMyAdmin)

• Apache (Servidor Web que nos permite ejecutar PHPMyAdmin y PHP en


un servidor)

Descargamos e instalamos XAMPP para el sistema operativo que estamos


trabajando.
Los pasos para instalar son muy sencillos:

Lo mínimo que debemos instalar es:


Una vez finalizada la instalación de todo el software debemos arrancar el
programa "XAMPP Control Panel":

Aparece la interfaz desde donde debemos iniciar el gestor de base de datos


MySQL:
Presionamos el botón "Start" tanto para MySQL como para Apache:

Si aparecen en verde significa que los programas se encuentran correctamente


en funcionamiento.
Creación de la base de datos MySQL.
Para crear la base de datos utilizaremos el programa PHPMyAdmin que lo
iniciamos presionando el botón "MySQL - Admin" del "XAMPP Control Panel":

Se nos abre una aplicación web PHPMyAdmin que nos permite administrar
nuestras bases de datos de MySQL:
Crearemos una base de datos seleccionando la opción "Nueva" que aparece
del lado izquierdo de la página.
En el siguiente diálogo debemos definir el nombre de nuestra base de datos, la
llamaremos "bd1":
Una vez que se crea la podemos ver que aparece en la columna izquierda y
podemos pasar a crear tablas en la misma. Crearemos la tabla artículos que
tendrá 3 campos:
Almacenaremos en la tabla articulos el codigo, descripcion y precio.
El campo 'codigo' será int'clave primaria' y auto_increment.
El campo 'descripcion' será varchar de 50.
El campo 'precio' será float.
Los datos a ingresar para cada campo para la creación de la tabla articulos
son:
Ya tenemos creada la base de datos: "bd1" y en ésta la tabla "articulos":

Paquete de Python necesario para conectarnos a MySQL.


Utilizaremos el programa 'pip' que vimos anteriormente para instalar el paquete
necesario para interconectar 'Python' y 'MySQL'.
Desde la línea de comandos ejecutamos el programa pip con el siguiente
paquete a instalar:

pip install mysql-connector

Luego de ejecutar el programa pip podemos ver que nos informa de la


instalación del paquete 'mysql-connector':

Conexión con el servidor de MySQL.


Controlar que el "XAMPP Control Panel" se encuentre en ejecución el servidor
de MySQL:
El primer programa que implementaremos nos conectaremos con el servidor de
MySQL y mostraremos todas las bases de datos existentes (una de esas
debería ser bd1)
Programa: ejercicio276.py
Ver video

import mysql.connector
conexion1=mysql.connector.connect(host="localhost
", user="root", passwd="")
cursor1=conexion1.cursor()
cursor1.execute("show databases")
for base in cursor1:
print(base)
conexion1.close()
El resultado de ejecutar este programa es:

Lo primero que hacemos es importar el módulo que nos permite conectarnos


con MySQL:

import mysql.connector

Del módulo importado llamamos a la función connect pasando la ubicación de


nuestro servidor que es 'localhost', el usuario que por defecto al instalar MySQL
se creó el usuario 'root' y la clave de ese usuario que tiene por defecto un string
vacío:

conexion1=mysql.connector.connect(host="localhost", user="root", passwd="")

Si por ejemplo el servidor de MySQL no se encuentra en ejecución el programa


se detendrá en esta línea informando un error.
Luego a partir del objeto 'conexion1' que es de la clase 'MySQLConnection'
llamamos al método 'cursor':

cursor1=conexion1.cursor()

A partir del objeto 'cursor1' llamamos al método execute y le pasamos como


parámetro un comando SQL, en este caso 'show databases':

cursor1.execute("show databases")

Mediante un for podemos ver todas las bases de datos existentes en nuestro
servidor de MySQL:

for base in cursor1:


print(base)

Finalmente cerramos la conexión con el servidor de MySQL:

conexion1.close()

Listado de todas las tablas de una base de datos de


MySQL.
Ahora implementaremos un programa que recupere todas las tablas
contenidos en una base de datos. Trabajaremos con la base de datos que
creamos desde el PHPMyAdmin llamada 'bd1'.
Programa: ejercicio277.py
Ver video

import mysql.connector

conexion1=mysql.connector.connect(host="localhost
",
user="root",
passwd="",
database="bd1")
cursor1=conexion1.cursor()
cursor1.execute("show tables")
for tabla in cursor1:
print(tabla)
conexion1.close()
El resultado de ejecutar este programa es:

Cuando nos conectamos con el servidor de MySQL indicamos en 'database' la


base de datos activa para cuando lancemos comandos SQL:

conexion1=mysql.connector.connect(host="localhost",
user="root",
passwd="",
database="bd1")

Luego de crear el cursor solicitamos que se ejecute el comando SQL 'show


tables' que nos retorna todas las tablas existentes de la base de datos activa
indicada cuando llamamos a 'connect':

cursor1=conexion1.cursor()
cursor1.execute("show tables")

Imprimimos con un for todas las tablas y cerramos la conexión:

for tabla in cursor1:


print(tabla)
conexion1.close()

Insertar filas en una tabla.


Ahora implementaremos un programa que inserte un par de filas en la tabla
'articulos'.
Programa: ejercicio278.py
Ver video

import mysql.connector

conexion1=mysql.connector.connect(host="localhost
",
user="root",
passwd="",
database="bd1")
cursor1=conexion1.cursor()
sql="insert into articulos(descripcion, precio) v
alues (%s,%s)"
datos=("naranjas", 23.50)
cursor1.execute(sql, datos)
datos=("peras", 34)
cursor1.execute(sql, datos)
datos=("bananas", 25)
cursor1.execute(sql, datos)
conexion1.commit()
conexion1.close()
Por el momento si queremos controlar que se han cargado las tres filas en la
tabla 'articulos' podemos abrir el 'PHPMyAdmin' y ver el contenido de la tabla:

Definimos un string con el comando SQL insert disponiendo la máscara %s


donde queremos que se sustituya por un valor que le pasaremos al método
execute:

sql="insert into articulos(descripcion, precio) values (%s,%s)"

La variable datos es una tupla que contiene los datos que se utilizarán en la
sustitución %s:

datos=("naranjas", 23.50)
Finalmente llamamos al método 'execute' y le pasamos las dos variables que
acabamos de crear:

cursor1.execute(sql, datos)

Es fundamental llamar al final al método 'commit' para que queden firmes los
comandos SQL 'insert':

conexion1.commit()

Recuperar todas las filas de una tabla.


Implementaremos un programa que solicite ejecutar un 'select' en la tabla
'articulos' y nos retorne todas sus filas.
Programa: ejercicio279.py
Ver video

import mysql.connector

conexion1=mysql.connector.connect(host="localhost
",
user="root",
passwd="",
database="bd1")
cursor1=conexion1.cursor()
cursor1.execute("select codigo, descripcion, prec
io from articulos")
for fila in cursor1:
print(fila)
conexion1.close()
Cuando ejecutamos el programa podemos ver que se recuperan todas las filas
de la tabla 'articulos':
Luego de conectarnos y crear un cursor procedemos a ejecutar el comando
'select', recorremos con un for el 'cursor1':

cursor1=conexion1.cursor()
cursor1.execute("select codigo, descripcion, precio from articulos")
for fila in cursor1:
print(fila)

Borrado y modificación de filas.


Las otras dos actividades fundamentales que podemos hacer con una tabla es
borrar filas y modificar datos.
Desarrollaremos un pequeño programa que borre el artículo cuyo código sea el
1 y modifique el precio del artículo cuyo código sea 3.
Programa: ejercicio280.py
Ver video
import mysql.connector

conexion1=mysql.connector.connect(host="localhost
",
user="root",
passwd="",
database="bd1")
cursor1=conexion1.cursor()
cursor1.execute("delete from articulos where codi
go=1")
cursor1.execute("update articulos set precio=50 w
here codigo=3")
conexion1.commit()
cursor1.execute("select codigo, descripcion, prec
io from articulos")
for fila in cursor1:
print(fila)
conexion1.close()
Cuando ejecutamos el programa podemos ver que se eliminó el artículo cuyo
código es 1 y se modificó el precio del artículo con código 3:
Luego de crear el cursor podemos llamar al método 'execute' varias veces y
pasar distintos comando SQL:

cursor1=conexion1.cursor()
cursor1.execute("delete from articulos where codigo=1")
cursor1.execute("update articulos set precio=50 where codigo=3")

Siempre que pasemos un comando SQL: insert, delete o update debemos


llamar al método commit para que quede firme los cambios en la base de
datos:

conexion1.commit()

Ejecutamos finalmente un 'select' para comprobar los cambios efectuados en la


tabla 'articulos':

cursor1.execute("select codigo, descripcion, precio from articulos")


for fila in cursor1:
print(fila)
Retornar

82 - MySQL : interfaz visual con


tkinter y acceso a la base de datos
Es muy posible que necesitemos en algunas situaciones acceder a una base
de datos de MySQL desde una aplicación con una interfaz visual.

Problema:
Desarrollar una aplicación visual con la librería tkinter que permita implementar
los algoritmos de carga de artículos, consulta por código y listado completo.
Seguiremos trabajando con la tabla 'articulos' que creamos en el concepto
anterior.
Las interfaz visual para la carga debe ser:

Las interfaz visual para la consulta:


Y finalmente la interfaz para el listado completo:

Para trabajar un poco más ordenado en la resolución de este problema lo


dividiremos en dos módulos 'formularioarticulos.py' y 'articulos.py'.
El primer paso será crear una carpeta llamada 'proyecto3' y dentro de esta
crearemos los dos módulos:
El módulo 'formularioarticulos.py' contiene toda la lógica de presentación de
datos y hace uso del otro módulo para el acceso a la base de datos MySQL.
módulo: formularioarticulos.py
Ver video

import tkinter as tk
from tkinter import ttk
from tkinter import messagebox as mb
from tkinter import scrolledtext as st
import articulos

class FormularioArticulos:
def __init__(self):
self.articulo1=articulos.Articulos()
self.ventana1=tk.Tk()
self.ventana1.title("Mantenimiento de art
ículos")
self.cuaderno1 = ttk.Notebook(self.ventan
a1)
self.carga_articulos()
self.consulta_por_codigo()
self.listado_completo()
self.cuaderno1.grid(column=0, row=0, padx
=10, pady=10)
self.ventana1.mainloop()

def carga_articulos(self):
self.pagina1 = ttk.Frame(self.cuaderno1)
self.cuaderno1.add(self.pagina1, text="Ca
rga de artículos")
self.labelframe1=ttk.LabelFrame(self.pagi
na1, text="Artículo")
self.labelframe1.grid(column=0, row=0, pa
dx=5, pady=10)
self.label1=ttk.Label(self.labelframe1, t
ext="Descripción:")
self.label1.grid(column=0, row=0, padx=4,
pady=4)
self.descripcioncarga=tk.StringVar()
self.entrydescripcion=ttk.Entry(self.labe
lframe1, textvariable=self.descripcioncarga)
self.entrydescripcion.grid(column=1, row=
0, padx=4, pady=4)
self.label2=ttk.Label(self.labelframe1, t
ext="Precio:")
self.label2.grid(column=0, row=1, padx=4,
pady=4)
self.preciocarga=tk.StringVar()
self.entryprecio=ttk.Entry(self.labelfram
e1, textvariable=self.preciocarga)
self.entryprecio.grid(column=1, row=1, pa
dx=4, pady=4)
self.boton1=ttk.Button(self.labelframe1,
text="Confirmar", command=self.agregar)
self.boton1.grid(column=1, row=2, padx=4,
pady=4)

def agregar(self):
datos=(self.descripcioncarga.get(), self.
preciocarga.get())
self.articulo1.alta(datos)
mb.showinfo("Información", "Los datos fue
ron cargados")
self.descripcioncarga.set("")
self.preciocarga.set("")

def consulta_por_codigo(self):
self.pagina2 = ttk.Frame(self.cuaderno1)
self.cuaderno1.add(self.pagina2, text="Co
nsulta por código")
self.labelframe2=ttk.LabelFrame(self.pagi
na2, text="Artículo")
self.labelframe2.grid(column=0, row=0, pa
dx=5, pady=10)
self.label1=ttk.Label(self.labelframe2, t
ext="Código:")
self.label1.grid(column=0, row=0, padx=4,
pady=4)
self.codigo=tk.StringVar()
self.entrycodigo=ttk.Entry(self.labelfram
e2, textvariable=self.codigo)
self.entrycodigo.grid(column=1, row=0, pa
dx=4, pady=4)
self.label2=ttk.Label(self.labelframe2, t
ext="Descripción:")
self.label2.grid(column=0, row=1, padx=4,
pady=4)
self.descripcion=tk.StringVar()
self.entrydescripcion=ttk.Entry(self.labe
lframe2, textvariable=self.descripcion, state="re
adonly")
self.entrydescripcion.grid(column=1, row=
1, padx=4, pady=4)
self.label3=ttk.Label(self.labelframe2, t
ext="Precio:")
self.label3.grid(column=0, row=2, padx=4,
pady=4)
self.precio=tk.StringVar()
self.entryprecio=ttk.Entry(self.labelfram
e2, textvariable=self.precio, state="readonly")
self.entryprecio.grid(column=1, row=2, pa
dx=4, pady=4)
self.boton1=ttk.Button(self.labelframe2,
text="Consultar", command=self.consultar)
self.boton1.grid(column=1, row=3, padx=4,
pady=4)

def consultar(self):
datos=(self.codigo.get(), )
respuesta=self.articulo1.consulta(datos)
if len(respuesta)>0:
self.descripcion.set(respuesta[0][0])
self.precio.set(respuesta[0][1])
else:
self.descripcion.set('')
self.precio.set('')
mb.showinfo("Información", "No existe
un artículo con dicho código")

def listado_completo(self):
self.pagina3 = ttk.Frame(self.cuaderno1)
self.cuaderno1.add(self.pagina3, text="Li
stado completo")
self.labelframe3=ttk.LabelFrame(self.pagi
na3, text="Artículo")
self.labelframe3.grid(column=0, row=0, pa
dx=5, pady=10)
self.boton1=ttk.Button(self.labelframe3,
text="Listado completo", command=self.listar)
self.boton1.grid(column=0, row=0, padx=4,
pady=4)
self.scrolledtext1=st.ScrolledText(self.l
abelframe3, width=30, height=10)
self.scrolledtext1.grid(column=0,row=1, p
adx=10, pady=10)

def listar(self):
respuesta=self.articulo1.recuperar_todos(
)
self.scrolledtext1.delete("1.0", tk.END)
for fila in respuesta:
self.scrolledtext1.insert(tk.END, "có
digo:"+str(fila[0])+"\ndescripción:"+fila[1]+"\np
recio:"+str(fila[2])+"\n\n")

aplicacion1=FormularioArticulos()
El módulo 'articulos.py' contiene toda la lógica de acceso a datos.
módulo: articulos.py

import mysql.connector

class Articulos:

def abrir(self):
conexion=mysql.connector.connect(host="lo
calhost",
use
r="root",
pas
swd="",
dat
abase="bd1")
return conexion

def alta(self, datos):


cone=self.abrir()
cursor=cone.cursor()
sql="insert into articulos(descripcion, p
recio) values (%s,%s)"
cursor.execute(sql, datos)
cone.commit()
cone.close()

def consulta(self, datos):


cone=self.abrir()
cursor=cone.cursor()
sql="select descripcion, precio from arti
culos where codigo=%s"
cursor.execute(sql, datos)
cone.close()
return cursor.fetchall()

def recuperar_todos(self):
cone=self.abrir()
cursor=cone.cursor()
sql="select codigo, descripcion, precio f
rom articulos"
cursor.execute(sql)
cone.close()
return cursor.fetchall()
Tener en cuenta que el módulo principal se encuentra en el archivo
'formularioarticulos.py' y es el que debemos ejecutar:

Cuando al programa lo ejecutemos desde la línea de comandos fuera del editor


VS Code debemos recordar de llamar al módulo principal:
Analicemos un poco el código del módulo 'formularioarticulos.py', lo primero
que hacemos es importar los módulos necesarios para implementar la interfaz
visual:

import tkinter as tk
from tkinter import ttk
from tkinter import messagebox as mb
from tkinter import scrolledtext as st

Otro import fundamental es el módulo 'articulos.py' donde tenemos


implementada la clase 'Articulos' que es la que se comunica con el gestor de
base de datos MySQL:

import articulos

La clase visual la hemos llamado 'FormularioArticulos' y en el método __init__


creamos un objeto de la clase 'Articulos' que se encuentra en el otro módulo:

class FormularioArticulos:
def __init__(self):
self.articulo1=articulos.Articulos()

También en el método __init__ llamamos a una serie de métodos para crear


cada una de las páginas del objeto de la clase 'Notebook':
self.ventana1=tk.Tk()
self.ventana1.title("Mantenimiento de artículos")
self.cuaderno1 = ttk.Notebook(self.ventana1)
self.carga_articulos()
self.consulta_por_codigo()
self.listado_completo()
self.cuaderno1.grid(column=0, row=0, padx=10, pady=10)
self.ventana1.mainloop()

Cuando desde la pestaña "Carga de artículos" se presiona el botón "Confirmar"


lo primero que hacemos es crear una tupla con los dos datos ingresados en los
controles "Entry":

def agregar(self):
datos=(self.descripcioncarga.get(), self.preciocarga.get())

Luego llamamos al método alta del objeto 'articulo1' y le pasamos la tupla con
los datos a añadir:

self.articulo1.alta(datos)
mb.showinfo("Información", "Los datos fueron cargados")
self.descripcion.set("")
self.precio.set("")

En este momento nos conviene analizar el método 'alta' de la clase 'Articulos'


que se encuentra en el otro módulo:

def alta(self, datos):


cone=self.abrir()
cursor=cone.cursor()
sql="insert into articulos(descripcion, precio) values (%s,%s)"
cursor.execute(sql, datos)
cone.commit()
cone.close()

En el método 'alta' abrimos la conexión con el MySQL, creamos un cursor y


llamamos seguidamente al método execute pasando un string con el comando
SQL 'insert' y los datos a almacenar. Llamamos al método commit de la
conexión y finalmente cerramos la conexión.
Consulta por código
Cuando se presiona el botón "Consultar" se ejecuta el método siguiente:

def consultar(self):
datos=(self.codigo.get(), )
respuesta=self.articulo1.consulta(datos)
if len(respuesta)>0:
self.descripcion.set(respuesta[0][0])
self.precio.set(respuesta[0][1])
else:
self.descripcion.set('')
self.precio.set('')
mb.showinfo("Información", "No existe un artículo con dicho código")

Creamos una tubla con un solo dato (es obligatoria la coma para que Python lo
considere una tupla):

datos=(self.codigo.get(), )

Llamamos al método consulta de la clase 'Articulos' que se encuentra en el otro


módulo. El método 'consulta' retorna una lista vacía si no existe el código de
artículo ingresado o una lista con una tupla en su interior.
El método 'consulta' de la clase 'Articulos' llama al método 'fetchall' del cursor
respectivo:

def consulta(self, datos):


cone=self.abrir()
cursor=cone.cursor()
sql="select descripcion, precio from articulos where codigo=%s"
cursor.execute(sql, datos)
cone.close()
return cursor.fetchall()

Listado completo
Para mostrar todas las filas de la tabla 'articulos' hemos dispuesto un objeto de
la clase 'scrolledtext':

def listar(self):
respuesta=self.articulo1.recuperar_todos()
self.scrolledtext1.delete("1.0", tk.END)
for fila in respuesta:
self.scrolledtext1.insert(tk.END, "código:"+str(fila[0])+
"\ndescripción:"+fila[1]+
"\nprecio:"+str(fila[2])+"\n\n")

Llamamos al método 'recuperar_todos' de la clase 'Articulos' y obtenemos una


lista con un conjunto de tuplas con cada fila de la tabla.
El algoritmo 'recuperar_todos' de la clase Articulos es:

def recuperar_todos(self):
cone=self.abrir()
cursor=cone.cursor()
sql="select codigo, descripcion, precio from articulos"
cursor.execute(sql)
cone.close()
return cursor.fetchall()

Problema propuesto
• Agregar dos pestañas al programa de administración de artículos que
permitan borrar un artículo ingresando su código y otra opción que
permita consultar y modificar la descripción y precio de un artículo.
La interfaces visuales a implementar son:
Ver video
Solución

Retornar
83 - MySQL : otras funcionalidades del
paquete mysql-connector
Hemos resuelto en los dos conceptos anteriores algoritmos en Python que
acceden a una base de datos de MySQL. Veremos otras funcionalidades que
nos provee el paquete mysql-connector.

Recuperar el valor del campo auto_increment en un


insert.
Cuando insertamos una fila en una tabla que contiene un campo que se auto
incrementa podemos recuperar dicho valor en el mismo momento que
efectuamos la inserción.
Programa: ejercicio281.py
Ver video

import mysql.connector

conexion1=mysql.connector.connect(host="localhost
",
user="root",
passwd="",
database="bd1")
cursor1=conexion1.cursor()
sql="insert into articulos(descripcion, precio) v
alues (%s,%s)"
datos=("naranjas", 23.50)
cursor1.execute(sql, datos)
conexion1.commit()
print("Valor del último codigo de artículo genera
do:", cursor1.lastrowid)
conexion1.close()
Luego de efectuar la inserción de una fila en la tabla 'articulos' procedemos a
acceder al atributo 'lastrowid' que almacena el código de artículo que se acaba
de generar.

Inserción de múltiples filas en una tabla.


La clase cursor a parte del método 'execute' cuenta con otro método llamado
'executemany' que tiene el objetivo de insertar múltiples filas de una tabla.
Programa: ejercicio282.py
Ver video

import mysql.connector

conexion1=mysql.connector.connect(host="localhost
",
user="root",
passwd="",
database="bd1")
cursor1=conexion1.cursor()
sql="insert into articulos(descripcion, precio) v
alues (%s,%s)"
filas=[ ("naranjas", 23.50),
("bananas", 34),
("peras", 21),
("sandía", 19.60) ]
cursor1.executemany(sql, filas)
conexion1.commit()
conexion1.close()
El método 'executemany' debe recibir en el segundo parámetro una lista cuyos
elementos sean una tupla por cada fila:

sql="insert into articulos(descripcion, precio) values (%s,%s)"


filas=[ ("naranjas", 23.50),
("bananas", 34),
("peras", 21),
("sandía", 19.60) ]
cursor1.executemany(sql, filas)

Si accedemos luego a la propiedad 'lastrowid' nos devuelve el código del último


código de artículo almacenando.

Creación de una base de datos y tablas.


En conceptos anteriores vimos como crear una base de datos de MySQL
utilizando la aplicación PHPMyAdmin, en algunas situaciones podemos
necesitar crear una base de datos desde el mismo programa de Python. La
misma metodología será si queremos crear tablas.
Programa: ejercicio283.py
Ver video

import mysql.connector

conexion1=mysql.connector.connect(host="localhost
",
user="root",
passwd="")
cursor1=conexion1.cursor()
sql="create database bd2"
cursor1.execute(sql)

sql="use bd2"
cursor1.execute(sql)

sql="""create table usuarios (


nombre varchar(30) primary key,
clave varchar(30)
)"""
cursor1.execute(sql)

conexion1.commit()
conexion1.close()
Lo primero que debemos notar que en la conexión al servidor de base de datos
MySQL no indicamos una "base de datos":

conexion1=mysql.connector.connect(host="localhost",
user="root",
passwd="")

Luego de crear el cursor procedemos a llamar al método 'execute' y le


pasamos el comando SQL 'create database' con el nombre de base de datos a
crear:

cursor1=conexion1.cursor()
sql="create database bd2"
cursor1.execute(sql)

Luego de crear la base de datos si queremos activarla para poder crear tablas,
insertar filas en tablas, consultarlas etc. debemos activarla mediante el
comando SQL 'use' con el nombre de la base de datos:

sql="use bd2"
cursor1.execute(sql)

Ya estando en uso la base de datos 'bd2' podemos efectuar la creación de una


tabla:

sql="""create table usuarios (


nombre varchar(30) primary key,
clave varchar(30)
)"""
cursor1.execute(sql)
Recordemos que las triple comillas nos permiten en Python definir un string de
múltiples líneas.
Luego de ejecutar este programa si entramos a PHPMyAdmin veremos que se
ha creado la base de datos 'bd2' y dentro de esta la tabla 'usuarios':

Se ejecutamos nuevamente el programa veremos que se genera un error


indicando que la base de datoas 'bd2' ya existe.

Borrar una base de datos.


Cuando queremos crear una base de datos que ya existe se genera un error,
podemos primero borrarla y luego ya si crearla sin problemas.
Programa: ejercicio284.py
Ver video

import mysql.connector
conexion1=mysql.connector.connect(host="localhost
",
user="root",
passwd="")
cursor1=conexion1.cursor()

sql="drop database if exists bd2"


cursor1.execute(sql)

sql="create database bd2"


cursor1.execute(sql)

sql="use bd2"
cursor1.execute(sql)

sql="""create table usuarios (


nombre varchar(30) primary key,
clave varchar(30)
)"""
cursor1.execute(sql)

conexion1.commit()
conexion1.close()
Este programa es una variante del anterior donde primero verificamos si existe
la base de datos 'bd2' y en caso afirmativo la eliminamos:

sql="drop database if exists bd2"


cursor1.execute(sql)
Una vez que borramos la base de datos 'bd2' en el caso que exista
procedemos a crearla:

sql="create database bd2"


cursor1.execute(sql)

Borrar una tabla y crear otra con el mismo nombre.


No se puede crear una tabla con el mismo nombre de una existente, en esos
casos debemos borrar la actual y crear una nueva.
Programa: ejercicio285.py
Ver video

import mysql.connector

conexion1=mysql.connector.connect(host="localhost
",
user="root",
passwd="",
database="bd2")
cursor1=conexion1.cursor()
sql="drop table if exists usuarios"
cursor1.execute(sql)

sql="""create table usuarios (


nombre varchar(30) primary key,
clave varchar(30)
)"""
cursor1.execute(sql)

conexion1.commit()
conexion1.close()
Para eliminar la tabla 'usuarios' si existe ejecutamos el siguiente comando
SQL:

sql="drop table if exists usuarios"


cursor1.execute(sql)

Una vez eliminada la tabla podemos crearla nuevamente:

sql="""create table usuarios (


nombre varchar(30) primary key,
clave varchar(30)
)"""
cursor1.execute(sql)

Retornar

84 - Manejo de excepciones en Python


Las excepciones son errores que se disparan durante la ejecución de un
programa. En Python podemos dejar que dichas excepciones detengan el
programa o en caso contrario escribir un algoritmo para reaccionar a dicha
situación.
Los ejemplos más comunes que podemos nombrar de excepciones:

• Tratar de convertir a entero un string que no contiene valores numéricos.

• Tratar de dividir por cero.

• Abrir un archivo de texto inexistente o que se encuentra bloqueado por


otra aplicación.

• Conectar con un servidor de bases de datos que no se encuentra activo.

• Acceder a subíndices de listas o tuplas inexistentes.

• Llamada a un método o función inexistente.


• Importar módulos que no existen.

La captura de excepciones nos permite crear programas mucho más robustos


y tolerante a fallas que ocurren en escasas situaciones, pero en caso que se
presenten disponemos de un algoritmo alternativo para reaccionar a dicha
situación evitando que el programa finalice su ejecución.

Problema:
Realizar la carga de dos números enteros por teclado e imprimir su suma,
luego preguntar si quiere seguir sumando valores.
Codificar dos programas uno que capture la excepción de ingreso de datos no
numéricos y el otro que no tenga en cuenta el tipo de entrada de datos.
Primero codificaremos sin la captura de excepciones.
Ver video
Programa: ejercicio296.py

while True:
valor1=int(input("Ingrese primer valor:"))
valor2=int(input("Ingrese segundo valor:"))
suma=valor1+valor2
print("La suma es", suma)
respuesta=input("Desea ingresar otro par de v
alores?[s/n]")
if respuesta=="n":
break
Disponemos un while infinito que solo terminará cuando el if contenido dentro
del while se verifique verdadero y se ejecute la instrucción break que finaliza
inmediatamente el while.
El algoritmo planteado funciona correctamente en casi todos los casos,
siempre y cuando el operador ingrese por teclado valores numéricos. En el
caso que el operador ingrese un valor no numérico el programa se interrumpe
mostrando la excepción generada:
Como podemos comprobar el programa finaliza si ingresamos la cadena 'juan'
en lugar de un número. Es un tipo de error que según el tipo de programa que
estamos desarrollando capturaremos ésta excepción, por ejemplo si es un
pequeño script que utilizaremos nosotros mismos es posible que este algoritmo
nos alcance y tengamos cuidado de cargar siempre valores enteros por
teclado.
Pero que pasa si el programa lo utilizará otro usuario que no tenga cuidado en
la entrada de datos, podemos modificar este programa para que no se
interrumpa al ingresar valores no numéricos y le informe con un mensaje que
valores están permitidos ingresar por teclado.
Programa: ejercicio297.py

while True:
try:
valor1=int(input("Ingrese primer valor:")
)
valor2=int(input("Ingrese segundo valor:"
))
suma=valor1+valor2
print("La suma es",suma)
except ValueError:
print("debe ingresar números.")
respuesta=input("Desea ingresar otro par de v
alores?[s/n]")
if respuesta=="n":
break
En el caso que el operador ingrese un valor no numérico el programa no se
interrumpe mostrando la excepción generada sino que se ejecuta un algoritmo
alternativo:

Para capturar las excepciones en Python aparecen dos palabras claves nuevas
try y except.
El algoritmo principal se dispone dentro del bloque try:

try:
valor1=int(input("Ingrese primer valor:"))
valor2=int(input("Ingrese segundo valor:"))
suma=valor1+valor2
print("La suma es",suma)
Siempre que el operador ingrese valores numéricos solo se ejecuta el bloque
del try, pero cuando ingresa un dato no numérico por teclado se genera la
excepción 'ValueError' que debe ser capturada luego de la palabra clave
except y seguida por el nombre de excepción capturada:

except ValueError:
print("debe ingresar números.")

El algoritmo que dispongamos en éste bloque puede hacer cualquier cosa, en


este caso solo informar al operador que debe ingresar solo números.
Luego de ejecutar el bloque 'except' continúa el programa activo con las
instrucciones siguiente sin su interrupción.

Retornar

85 - Excepciones estándar de Python


Python provee un conjunto de excepciones por defecto que podemos hace uso
en nuestros programas.
Ver video
Algunas de las excepciones más comunes que podemos utilizar son:
• ValueError: Se genera cuando una operación o función recibe un
argumento que tiene un valor inapropiado como vimos en el concepto
anterior al tratar de convertir un string a entero siendo que el string no
contiene valores numéricos.
• IndexError: Se genera cuando un subíndice de una secuencia (tupla,
lista, string) está fuera de rango. Por ejemplo en una lista de 5 elementos
queremos acceder al elemento con subíndice 70.
• NameError: Se genera cuando llamamos a una función, método o
tratamos de acceder a una variable inexistente.

• TypeError: Se genera cuando una operación o función se aplica a un


tipo de dato inapropiado. Por ejemplo si queremos sumar un entero y un
string:

• ModuleNotFoundError: Se genera cuando la declaración de un import


tiene problemas al intentar cargar el módulo inexistente :

• ZeroDivisionError: Se genera cuando intentamos dividir una variable o


valor por cero:

• OverflowError: Se genera cuando un resultado de una operación


aritmética con valores reales (no enteros) es demasiado grande para ser
representado:
• KeyError: Se genera cuando no se encuentra una clave en un
diccionario:

Un listado completo de las excepciones estándar de Python las puede


consultar aquí.

Ejemplos de problemas que capturan excepciones.

Problema:
Realizar la carga de dos números por teclado e imprimir la división del primero
respecto al segundo, capturar la excepción ZeroDivisionError.
Programa: ejercicio298.py

try:
valor1=int(input("Ingrese dividendo:"))
valor2=int(input("Ingrese divisor:"))
division=valor1/valor2
print("El resultado de la división es", divis
ion)
except ZeroDivisionError:
print("No se puede dividir por cero.")

Problema:
Almacenar en una tupla los nombres de meses del año. Solicitar el ingreso del
número de mes y mostrar seguidamente el nombre de dicho mes. Capturar la
excepción IndexError.
Programa: ejercicio299.py

meses=("enero","febrero","marzo","abril","mayo","
junio",
"julio","agosto","septiembre","octubre","n
oviembre","diciembre")
try:
nromes=int(input("Ingrese un número de mes [1
-12]:"))
print(meses[nromes-1])
except IndexError:
print("En número de mes debe ir entre 1 y 12"
)
Con este algoritmo si el operador ingresa un valor superior a 12 luego se
captura la excepción IndexError. Pero tenemos el problema si carga un valor 0
o inferior a 0 luego las tuplas pueden disponer valores negativos, por lo que
estos casos lo podemos resolver con un if:

meses=("enero","febrero","marzo","abril","mayo","junio",
"julio","agosto","septiembre","octubre","noviembre","diciembre")
try:
nromes=int(input("Ingrese un número de mes [1-12]:"))
if nromes>0:
print(meses[nromes-1])
else:
print("En número de mes debe ir entre 1 y 12")
except IndexError:
print("En número de mes debe ir entre 1 y 12")

Captura de múltiples excepciones con un try.


En un algoritmo se pueden presentar múltiples tipos de excepciones. Veamos
la sintaxis para su captura con un ejemplo.

Problema:
Realizar la carga de dos números por teclado e imprimir la división del primero
respecto al segundo, capturar las excepciones ZeroDivisionError y ValueError.
Programa: ejercicio300.py

try:
valor1=int(input("Ingrese dividendo:"))
valor2=int(input("Ingrese divisor:"))
division=valor1/valor2
print("El resultado de la división es", divis
ion)
except ZeroDivisionError:
print("No se puede dividir por cero.")
except ValueError:
print("Los valores a ingresar deben ser enter
os")
Debemos disponer los dos bloques 'except' a la misma altura indicando el
nombre de la excepción a capturar:

except ZeroDivisionError:
print("No se puede dividir por cero.")
except ValueError:
print("Los valores a ingresar deben ser enteros")

Captura de todas las excepciones sin discriminar el tipo.


En algunas situaciones podemos disponer un bloque try/except sin especificar
el o los nombres de las excepciones a capturar.

Problema:
Realizar la carga de dos números por teclado e imprimir la división del primero
respecto al segundo. Capturar cualquier tipo de excepción que se dispare.
Programa: ejercicio301.py

try:
valor1=int(input("Ingrese dividendo:"))
valor2=int(input("Ingrese divisor:"))
division=valor1/valor2
print("El resultado de la división es", divis
ion)
except:
print("Problemas con la entrada u operación")
Como podemos ver no disponemos un nombre de excepción después de la
palabra clave 'except':

except:
print("Problemas con la entrada u operación")

Nuestro algoritmo que responde a cualquier excepción que se dispara siempre


será muy general ya que no analizamos en particular que excepción se generó.

Retornar

86 - Instrucción finally en un bloque


try
Ver video
Hemos visto que la sintaxis para la captura de excepciones es:

try:
[algoritmo principal]
except [nombre de la excepción 1]:
[algoritmo alternativo 1]
except [nombre de la excepción 2]:
[algoritmo alternativo 2]
except [nombre de la excepción 3]:
[algoritmo alternativo 3]

Hay otra sección opcional de la cláusula 'try' llamada 'finally':

try:
[algoritmo principal]
except [nombre de la excepción 1]:
[algoritmo alternativo 1]
except [nombre de la excepción 2]:
[algoritmo alternativo 2]
except [nombre de la excepción 3]:
[algoritmo alternativo 3]
finally:
[algoritmo que siempre se ejecuta]

Cuando en el algoritmo principal se genera una excepción las instrucciones


que continúan nunca se ejecutarán ya que pasa a ejecutar el bloque del
'except'. Hay situaciones donde queremos que haya un algoritmo que siempre
se ejecute ya sea que se dispare una excepción o no.
Veamos algunos ejemplos donde es conveniente emplear el bloque finally.

Problema:
Almacenar una serie de string en un archivo de texto. Tratar de llamar al
método 'write' pasando un entero.
Programa: ejercicio301.py

try:
archi1=open("datos.txt","w")
archi1.write("Primer línea.\n")
archi1.write("Segunda línea.\n")
archi1.write("Tercer línea.\n")
archi1.write(3334)
except TypeError:
print("No se puede grabar un entero con write
")
finally:
archi1.close()
print("Se cerró el archivo")
Si ejecutamos este programa al llamar al método write con un dato entero se
genera la excepción 'TypeError':

archi1.write(3334)
except TypeError:
print("No se puede grabar un entero con write")

Luego de capturarse la excepción 'TypeError' se ejecuta el bloque 'finally'


donde se cierra el archivo:

finally:
archi1.close()
print("Se cerró el archivo")

Si modificamos el programa y borramos la línea donde grabamos el entero no


se capturan excepciones pero si se ejecuta el bloque 'finally' donde se cierra el
archivo.
Si no existiera la instrucción finally nuestro programa quedaría:
try:
archi1=open("datos.txt","w")
archi1.write("Primer línea.\n")
archi1.write("Segunda línea.\n")
archi1.write("Tercer línea.\n")
archi1.write(3334)
archi1.close()
print("Se cerró el archivo")
except TypeError:
print("No se puede grabar un entero con write")

De esta forma el algoritmo tiene el problema que nunca cerrará el archivo ya


que no se ejecutará el bloque:

archi1.close()
print("Se cerró el archivo")

Es muy común utilizar la cláusula 'finally' para liberar recursos solicitados


dentro del bloque 'try'. Veamos con otro ejemplo ya resuelto anteriormente
accediendo a una base de datos de MySQL.

Problema:
Conectarse a una base de datos de MySQL y ejecutar un comando SQL
incorrecto.
Programa: ejercicio302.py

import mysql.connector

try:
conexion1=mysql.connector.connect(host="local
host", user="root", passwd="")
cursor1=conexion1.cursor()
cursor1.execute("show databasesqqqqqqqq")
for base in cursor1:
print(base)
except mysql.connector.errors.ProgrammingError:
print("Error en el comando SQL")
finally:
conexion1.close()
print("Se cerró la conexión a la base de dato
s")
Hemos definido un comando SQL incorrecto al llamar al método 'execute':

cursor1.execute("show databasesqqqqqqqq")

Luego se captura la excepción 'ProgrammingError' que se encuentra en el


módulo 'mysql.connector.errors':

except mysql.connector.errors.ProgrammingError:
print("Error en el comando SQL")

Indistintamente que dispongamos un comando SQL correcto o incorrecto luego


se ejecuta el bloque finally donde cerramos la conexión:

finally:
conexion1.close()
print("Se cerró la conexión a la base de datos")

Retornar

87 - SQLite : Base de datos desde


Python
Ver video
La segunda base de datos que veremos su acceso desde Python es SQLite.

Se encuentra invitado para desarrollar un curso completo de SQLite Ya!


SQLite también es un gestor de bases de datos relacional pero con objetivos
muy diferentes a MySQL, SQLServer, Oracle etc.
Este gestor de base de datos tiene por objetivo ser parte de la misma
aplicación con la que colabora, es decir no cumple los conceptos de cliente y
servidor.
Para entender sus usos podemos dar algunos ejemplos donde se utiliza el
gestor SQLite:

• Firefox usa SQLite para almacenar los favoritos, el historial, las cookies
etc.

• También el navegador Opera usa SQLite.

• La aplicación de comunicaciones Skype de Microsoft utiliza SQLite

• Los sistemas operativos Android y iOS adoptan SQLite para permitir el


almacenamiento y recuperación de datos.

SQLite es Open Source y se ha instalado por defecto con Python, es decir


forma parte de la biblioteca estándar, no tenemos que instalar ningún módulo
con pip.
Si nuestra aplicación necesita almacenar gran cantidad de información local
con cierta estructura el empleo de SQLite es nuestra principal opción.

Creación de una base de datos y tablas.


En principio no se requiere tener más que Python instalado para poder trabajar
con SQLite. Podemos desde nuestra propia aplicación crear la base de datos y
sus tablas.
Programa: ejercicio303.py

import sqlite3

conexion=sqlite3.connect("bd1.db")
try:
conexion.execute("""create table articulos (
codigo integer prim
ary key autoincrement,
descripcion text,
precio real
)""")
print("se creo la tabla articulos")
except sqlite3.OperationalError:
print("La tabla articulos ya existe")
conexion.close()
Para poder trabajar con bases de datos de tipo SQLite debemos primero
importar el módulo 'sqlite3':

import sqlite3

Para crear o abrir una conexión con una base de datos existente debemos
llamar a la función 'connect' del módulo 'sqlite3':

conexion=sqlite3.connect("bd1.db")

La primera vez que ejecutemos este programa como no existe la base de datos
'bd1.db' se crea, consiste en un único archivo que se localiza en la misma
carpeta de nuestra aplicación:

Disponemos un try/except al momento de crear la tabla debido a que si


ejecutamos por segunda vez este programa se tratará de crear nuevamente la
tabla 'articulos' y al ya existir se genera una excepción de tipo
'OperationalError':
try:
conexion.execute("""create table articulos (
codigo integer primary key autoincrement,
descripcion text,
precio real
)""")
print("se creo la tabla articulos")
except sqlite3.OperationalError:
print("La tabla articulos ya existe")

Si no queremos disponer la excepción 'OperationalError' podemos modificar el


comando SQL de la creación de la tabla con la sintaxis:

import sqlite3
conexion=sqlite3.connect("bd1.db")
conexion.execute("""create table if not exists articulos (
codigo integer primary key AUTOINCREMENT,
descripcion text,
precio real
)""")
conexion.close()

Insertar filas en una tabla.


Ahora implementaremos un programa que inserte un par de filas en la tabla
'articulos' de la base de datos 'bd1' que acabamos de crear con el programa
anterior.
Programa: ejercicio304.py

import sqlite3

conexion=sqlite3.connect("bd1.db")
conexion.execute("insert into articulos(descripci
on,precio) values (?,?)", ("naranjas", 23.50))
conexion.execute("insert into articulos(descripci
on,precio) values (?,?)", ("peras", 34))
conexion.execute("insert into articulos(descripci
on,precio) values (?,?)", ("bananas", 25))
conexion.commit()
conexion.close()
Llamamos a execute y le pasamos como primer parámetro un comando SQL
'insert' con el caracter '?' indicamos las posiciones donde se van a sustituir. El
segundo parámetro es una tupla con los datos que se utilizarán en la
sustitución:

conexion.execute("insert into articulos(descripcion,precio) values (?,?)", ("nar


anjas", 23.50))

Luego de efectuar todos los insert debemos llamar a 'commit' para que se
actualicen los datos realmente en la tabla de la base de datos:

conexion.commit()

Recuperar todas las filas de una tabla.


Implementaremos un programa que solicite ejecutar un 'select' en la tabla
'articulos' y nos retorne todas sus filas.
Programa: ejercicio305.py

import sqlite3

conexion=sqlite3.connect("bd1.db")
cursor=conexion.execute("select codigo,descripcio
n,precio from articulos")
for fila in cursor:
print(fila)
conexion.close()
Si ejecutamos este programa luego de haber cargado las tres filas del ejercicio
anterior el resultado será el siguiente:
El método execute retorna un objeto de la clase Cursor:

cursor=conexion.execute("select codigo,descripcion,precio from articulos")

Recuperar una fila de una tabla.


Implementaremos un programa que solicite el ingreso del código de un
producto y luego nos muestre su descripción y precio.
Programa: ejercicio306.py

import sqlite3

conexion=sqlite3.connect("bd1.db")
codigo=int(input("Ingrese el código de un artícul
o:"))
cursor=conexion.execute("select descripcion,preci
o from articulos where codigo=?", (codigo, ))
fila=cursor.fetchone()
if fila!=None:
print(fila)
else:
print("No existe un artículo con dicho código
.")
conexion.close()
El resultado de este comando SQL select puede ser de una fila si existe el
código de artículo ingresado o cero filas:

cursor=conexion.execute("select codigo,descripcion,precio from articulos where c


odigo=?", (codigo, ))
fila=cursor.fetchone()

El método fechone de la clase Cursor retorna una tupla con la fila de la tabla
que coincide con el código ingresado o retorna 'None':

fila=cursor.fetchone()
if fila!=None:
print(fila)
else:
print("No existe un artículo con dicho código.")

Recuperar varias filas de una tabla.


Implementaremos un programa que solicite el ingreso de un precio y luego nos
muestre la descripción de todos los artículos con un precio inferior al
ingresado.
Programa: ejercicio307.py

import sqlite3

conexion=sqlite3.connect("bd1.db")
precio=float(input("Ingrese un precio:"))
cursor=conexion.execute("select descripcion from
articulos where precio<?", (precio, ))
filas=cursor.fetchall()
if len(filas)>0:
for fila in filas:
print(fila)
else:
print("No existen artículos con un precio men
or al ingresado.")
conexion.close()
En este caso el resultado del comando 'select' pueden ser muchas filas:

cursor=conexion.execute("select descripcion from articulos where precio<?", (pre


cio, ))

Llamamos al método 'fetchall' de la clase Cursor y nos retorna una lista con
todas las filas de la tabla que cumplen la condición de tener un precio inferior al
ingresado:

filas=cursor.fetchall()

En el caso que la lista no esté vacía procedemos a imprimirla:

if len(filas)>0:
for fila in filas:
print(fila)
else:
print("No existen artículos con un precio menor al ingresado.")

Retornar

88 - SQLite : interfaz visual con tkinter


y acceso a la base de datos
Es muy posible que necesitemos en algunas situaciones acceder a una base
de datos de SQLite desde una aplicación con una interfaz visual.
Implementaremos el mismo problema que resolvimos cuando trabajamos con
el gestor de base de datos MySQL.

Problema:
Ver video
Desarrollar una aplicación visual con la librería tkinter que permita implementar
los algoritmos de carga de artículos, consulta por código y listado completo.
Trabajaremos con la base de datos 'bd1.db' que creamos en el concepto
anterior.
Las interfaz visual para la carga debe ser:

Las interfaz visual para la consulta:


Y finalmente la interfaz para el listado completo:

Para trabajar un poco más ordenado en la resolución de este problema lo


dividiremos en dos módulos 'formularioarticulos.py' y 'articulos.py'.
El primer paso será crear una carpeta llamada 'proyecto4' y dentro de esta
crearemos los dos módulos:
El módulo 'formularioarticulos.py' contiene toda la lógica de presentación de
datos y hace uso del otro módulo para el acceso a la base de datos SQLite.
módulo: formularioarticulos.py

import tkinter as tk
from tkinter import ttk
from tkinter import messagebox as mb
from tkinter import scrolledtext as st
import articulos

class FormularioArticulos:
def __init__(self):
self.articulo1=articulos.Articulos()
self.ventana1=tk.Tk()
self.ventana1.title("Mantenimiento de art
ículos")
self.cuaderno1 = ttk.Notebook(self.ventan
a1)
self.carga_articulos()
self.consulta_por_codigo()
self.listado_completo()
self.cuaderno1.grid(column=0, row=0, padx
=10, pady=10)
self.ventana1.mainloop()

def carga_articulos(self):
self.pagina1 = ttk.Frame(self.cuaderno1)
self.cuaderno1.add(self.pagina1, text="Ca
rga de artículos")
self.labelframe1=ttk.LabelFrame(self.pagi
na1, text="Artículo")
self.labelframe1.grid(column=0, row=0, pa
dx=5, pady=10)
self.label1=ttk.Label(self.labelframe1, t
ext="Descripción:")
self.label1.grid(column=0, row=0, padx=4,
pady=4)
self.descripcioncarga=tk.StringVar()
self.entrydescripcion=ttk.Entry(self.labe
lframe1, textvariable=self.descripcioncarga)
self.entrydescripcion.grid(column=1, row=
0, padx=4, pady=4)
self.label2=ttk.Label(self.labelframe1, t
ext="Precio:")
self.label2.grid(column=0, row=1, padx=4,
pady=4)
self.preciocarga=tk.StringVar()
self.entryprecio=ttk.Entry(self.labelfram
e1, textvariable=self.preciocarga)
self.entryprecio.grid(column=1, row=1, pa
dx=4, pady=4)
self.boton1=ttk.Button(self.labelframe1,
text="Confirmar", command=self.agregar)
self.boton1.grid(column=1, row=2, padx=4,
pady=4)

def agregar(self):
datos=(self.descripcioncarga.get(), self.
preciocarga.get())
self.articulo1.alta(datos)
mb.showinfo("Información", "Los datos fue
ron cargados")
self.descripcioncarga.set("")
self.preciocarga.set("")

def consulta_por_codigo(self):
self.pagina2 = ttk.Frame(self.cuaderno1)
self.cuaderno1.add(self.pagina2, text="Co
nsulta por código")
self.labelframe2=ttk.LabelFrame(self.pagi
na2, text="Artículo")
self.labelframe2.grid(column=0, row=0, pa
dx=5, pady=10)
self.label1=ttk.Label(self.labelframe2, t
ext="Código:")
self.label1.grid(column=0, row=0, padx=4,
pady=4)
self.codigo=tk.StringVar()
self.entrycodigo=ttk.Entry(self.labelfram
e2, textvariable=self.codigo)
self.entrycodigo.grid(column=1, row=0, pa
dx=4, pady=4)
self.label2=ttk.Label(self.labelframe2, t
ext="Descripción:")
self.label2.grid(column=0, row=1, padx=4,
pady=4)
self.descripcion=tk.StringVar()
self.entrydescripcion=ttk.Entry(self.labe
lframe2, textvariable=self.descripcion, state="re
adonly")
self.entrydescripcion.grid(column=1, row=
1, padx=4, pady=4)
self.label3=ttk.Label(self.labelframe2, t
ext="Precio:")
self.label3.grid(column=0, row=2, padx=4,
pady=4)
self.precio=tk.StringVar()
self.entryprecio=ttk.Entry(self.labelfram
e2, textvariable=self.precio, state="readonly")
self.entryprecio.grid(column=1, row=2, pa
dx=4, pady=4)
self.boton1=ttk.Button(self.labelframe2,
text="Consultar", command=self.consultar)
self.boton1.grid(column=1, row=3, padx=4,
pady=4)

def consultar(self):
datos=(self.codigo.get(), )
respuesta=self.articulo1.consulta(datos)
if len(respuesta)>0:
self.descripcion.set(respuesta[0][0])
self.precio.set(respuesta[0][1])
else:
self.descripcion.set('')
self.precio.set('')
mb.showinfo("Información", "No existe
un artículo con dicho código")

def listado_completo(self):
self.pagina3 = ttk.Frame(self.cuaderno1)
self.cuaderno1.add(self.pagina3, text="Li
stado completo")
self.labelframe3=ttk.LabelFrame(self.pagi
na3, text="Artículo")
self.labelframe3.grid(column=0, row=0, pa
dx=5, pady=10)
self.boton1=ttk.Button(self.labelframe3,
text="Listado completo", command=self.listar)
self.boton1.grid(column=0, row=0, padx=4,
pady=4)
self.scrolledtext1=st.ScrolledText(self.l
abelframe3, width=30, height=10)
self.scrolledtext1.grid(column=0,row=1, p
adx=10, pady=10)

def listar(self):
respuesta=self.articulo1.recuperar_todos(
)
self.scrolledtext1.delete("1.0", tk.END)
for fila in respuesta:
self.scrolledtext1.insert(tk.END, "có
digo:"+str(fila[0])+"\ndescripción:"+fila[1]+"\np
recio:"+str(fila[2])+"\n\n")

aplicacion1=FormularioArticulos()
El módulo 'articulos.py' contiene toda la lógica de acceso a SQLite.
módulo: articulos.py

import sqlite3

class Articulos:

def abrir(self):
conexion=sqlite3.connect("c:/programaspyt
hon/bd1.db")
return conexion
def alta(self, datos):
cone=self.abrir()
cursor=cone.cursor()
sql="insert into articulos(descripcion, p
recio) values (?,?)"
cursor.execute(sql, datos)
cone.commit()
cone.close()

def consulta(self, datos):


try:
cone=self.abrir()
cursor=cone.cursor()
sql="select descripcion, precio from
articulos where codigo=?"
cursor.execute(sql, datos)
return cursor.fetchall()
finally:
cone.close()

def recuperar_todos(self):
try:
cone=self.abrir()
cursor=cone.cursor()
sql="select codigo, descripcion, prec
io from articulos"
cursor.execute(sql)
return cursor.fetchall()
finally:
cone.close()
Tener en cuenta que el módulo principal se encuentra en el archivo
'formularioarticulos.py' y es el que debemos ejecutar:

Cuando al programa lo ejecutemos desde la línea de comandos fuera del editor


VS Code debemos recordar de llamar al módulo principal:
Analicemos un poco el código del módulo 'formularioarticulos.py', lo primero
que hacemos es importar los módulos necesarios para implementar la interfaz
visual:

import tkinter as tk
from tkinter import ttk
from tkinter import messagebox as mb
from tkinter import scrolledtext as st

Otro import fundamental es el módulo 'articulos.py' donde tenemos


implementada la clase 'Articulos' que es la que se comunica con la base de
datos SQLite:

import articulos

La clase visual la hemos llamado 'FormularioArticulos' y en el método __init__


creamos un objeto de la clase 'Articulos' que se encuentra en el otro módulo:

class FormularioArticulos:
def __init__(self):
self.articulo1=articulos.Articulos()
También en el método __init__ llamamos a una serie de métodos para crear
cada una de las páginas del objeto de la clase 'Notebook':

self.ventana1=tk.Tk()
self.ventana1.title("Mantenimiento de artículos")
self.cuaderno1 = ttk.Notebook(self.ventana1)
self.carga_articulos()
self.consulta_por_codigo()
self.listado_completo()
self.cuaderno1.grid(column=0, row=0, padx=10, pady=10)
self.ventana1.mainloop()

Cuando desde la pestaña "Carga de artículos" se presiona el botón "Confirmar"


lo primero que hacemos es crear una tupla con los dos datos ingresados en los
controles "Entry":

def agregar(self):
datos=(self.descripcioncarga.get(), self.preciocarga.get())

Luego llamamos al método alta del objeto 'articulo1' y le pasamos la tupla con
los datos a añadir:

self.articulo1.alta(datos)
mb.showinfo("Información", "Los datos fueron cargados")
self.descripcioncarga.set("")
self.preciocarga.set("")

En este momento nos conviene analizar el método 'alta' de la clase 'Articulos'


que se encuentra en el otro módulo:

def alta(self, datos):


cone=self.abrir()
cursor=cone.cursor()
sql="insert into articulos(descripcion, precio) values (?,?)"
cursor.execute(sql, datos)
cone.commit()
cone.close()
En el método 'alta' abrimos la conexión con el SQLite, creamos un cursor y
llamamos seguidamente al método execute pasando un string con el comando
SQL 'insert' y los datos a almacenar. Llamamos al método commit de la
conexión y finalmente cerramos la conexión.
El método para abrir la conexión es:

def abrir(self):
conexion=sqlite3.connect("c:/programaspython/bd1.db")
return conexion

Es importante especificar el path donde se encuentra el archivo 'bd1.db' si


nuestro programa en Python se encuentra en otra carpeta.
Consulta por código
Cuando se presiona el botón "Consultar" se ejecuta el método siguiente:

def consultar(self):
datos=(self.codigo.get(), )
respuesta=self.articulo1.consulta(datos)
if len(respuesta)>0:
self.descripcion.set(respuesta[0][0])
self.precio.set(respuesta[0][1])
else:
self.descripcion.set('')
self.precio.set('')
mb.showinfo("Información", "No existe un artículo con dicho código")

Creamos una tubla con un solo dato (es obligatoria la coma para que Python lo
considere una tupla:

datos=(self.codigo.get(), )

Llamamos al método consulta de la clase 'Articulos' que se encuentra en el otro


módulo. El método 'consulta' retorna una lista vacía si no existe el código de
artículo ingresado o una lista con una tupla en su interior.
El método 'consulta' de la clase 'Articulos' llama al método 'fetchall' del cursor
respectivo:

def consulta(self, datos):


try:
cone=self.abrir()
cursor=cone.cursor()
sql="select descripcion, precio from articulos where codigo=?"
cursor.execute(sql, datos)
return cursor.fetchall()
finally:
cone.close()

Listado completo
Para mostrar todas las filas de la tabla 'articulos' hemos dispuesto un objeto de
la clase 'scrolledtext':

def listar(self):
respuesta=self.articulo1.recuperar_todos()
self.scrolledtext1.delete("1.0", tk.END)
for fila in respuesta:
self.scrolledtext1.insert(tk.END, "código:"+str(fila[0])+
"\ndescripción:"+fila[1]+
"\nprecio:"+str(fila[2])+"\n\n")

Llamamos al método 'recuperar_todos' de la clase 'Articulos' y obtenemos una


lista con un conjunto de tuplas con cada fila de la tabla.
El algoritmo 'recuperar_todos' de la clase Articulos es:

def recuperar_todos(self):
try:
cone=self.abrir()
cursor=cone.cursor()
sql="select codigo, descripcion, precio from articulos"
cursor.execute(sql)
return cursor.fetchall()
finally:
cone.close()

Problema propuesto
• Agregar dos pestañas al programa de administración de artículos que
permitan borrar un artículo ingresando su código y otra opción que
permita consultar y modificar la descripción y precio de un artículo.
La interfaces visuales a implementar son:

Ver video
Solución

Retornar
89 - Python: f-strings para formateo
de cadenas de caracteres
Ver video
En las últimas versiones se ha agregado al lenguaje Python la posibilidad de
definir string y dentro hacer la sustitución de variables.
Veamos con un ejemplo cual es la sintaxis para implementar los f-strings en
Python.

Problema:
Ingresar por teclado dos enteros, calcular su suma y luego mostrar un mensaje
de los dos valores ingresados y su suma.
Programa: ejercicio308.py

valor1=int(input("Ingrese primer valor:"))


valor2=int(input("Ingrese segundo valor:"))
suma=valor1+valor2
print(f"La suma de {valor1} y {valor2} es {suma}"
)
Para indicar que un string en Python contendrá variables a ser sustituidas
debemos anteceder el caracter "f":

print(f"La suma de {valor1} y {valor2} es {suma}")

Las variables a ser sustituidas por su valor deben estar encerradas entre
llaves.
El resultado de la ejecución es:
No olvidar el caracter "f" previo a la declaración del string sino el resulta será:

La suma de {valor1} y {valor2} es {suma}

Problema:
Definir una lista con 5 valores enteros. Mostrar los 5 valores formateados a
derecha junto a su suma.
Programa: ejercicio309.py

lista=[2000, 500, 17000, 24, 7]


for elemento in lista:
print(f"{elemento:10}")
print("----------")
print(f"{sum(lista):10}")
El resultado de la ejecución es:
Cuando disponemos entre llaves la variable a sustituir podemos agregar luego
dos puntos y la cantidad de espacios que ocupará la variable:

print(f"{elemento:10}")

También otra posibilidad es indicar entre llaves la llamada a una función (la
función sum retorna la suma de toda la lista):

print(f"{sum(lista):10}")

Problema:
Definir una lista con 5 valores flotantes con distintas cantidades de decimales.
Mostrar los números solo con dos decimales.
Programa: ejercicio310.py

lista=[30.195, 400.2, 20.5555, 18.34, 67.0]


for elemento in lista:
print(f"{elemento:10.2f}")
El resultado de la ejecución es:
Acotaciones
• Si queremos insertar los caracteres de apertura o cerrado de llaves en
un f-strings debemos duplicarlos para que lo interprete Python:

• valor1=10

• print(f"{{valor1}} tiene el valor {valor1}")

Luego el string que se imprime en pantalla es:

{valor1} tiene el valor 10

• Podemos utilizar tanto el caracter "f" minúscula como el caracter "F"


mayúscula para indicar que se trata de un f-strings.

• valor1=10

• print(F"{{valor1}} tiene el valor {valor1}")

• Se puede utilizar los f-strings para cadenas de múltiples líneas:

• valor1=1000

• valor2=340

• suma=valor1+valor2

• cadena=f"""

• {valor1:5}

• {valor2:5}
• -----

• {suma:5}
• """

• print(cadena)

El resultado de la ejecución es:

1000
340
-----
1340

• Anteriormente sin la sintaxis de los f-strings debíamos convertir todos los


datos a string y concatenarlos:

• valor1=int(input("Ingrese primer valor:"))

• valor2=int(input("Ingrese segundo valor:"))

• suma=valor1+valor2

• print("La suma de "+str(valor1)+" y "+str(valor2)+" es "+str(suma))

También podíamos utilizar el método format:

valor1=int(input("Ingrese primer valor:"))


valor2=int(input("Ingrese segundo valor:"))
suma=valor1+valor2
print("La suma de {} y {} es {}".format(valor1, valor2, suma))

Con la llegada de los f-strings el código fuente de nuestro programa es


mucho más legible.

Retornar

90 - Recursividad: Conceptos básicos


Ver video
La recursividad es una técnica de programación que nos permite que un
bloque de instrucciones se ejecute n veces. Remplaza en ocasiones a
estructuras repetitivas.
La recursividad es un concepto difícil de entender en principio, pero luego de
analizar diferentes problemas aparecen puntos comunes.
En Python las funciones o métodos pueden llamarse a sí mismos. Si dentro de
una función o método existe la llamada a sí mismo decimos que la función o
método es recursivo.
Cuando una función o método se llama a sí mismo, se asigna espacio en la
pila para las nuevas variables locales y parámetros.
Al volver de una llamada recursiva, se recuperan de la pila las variables locales
y los parámetros antiguos y la ejecución se reanuda en el punto de la llamada
al método.

Problema 1:
Implementación de una función recursiva.
Programa: ejercicio311.py

def repetir():
repetir()

repetir()
La función repetir es recursiva porque dentro de la función se llama a sí misma.
Cuando ejecuta este programa se bloqueará y generará una excepción:
"RecursionError: maximum recursion depth exceeded"
Analicemos como funciona:
Se llama la función repetir.
Hay que tener en cuenta que cada vez que se llama a una función se reservan
un conjunto de bytes de la memoria que se liberarán cuando finalice su
ejecución.
La primera línea de la función llama a la función repetir, es decir que se
reservan más bytes nuevamente. Se ejecuta nuevamente una instancia de la
función repetir y así sucesivamente hasta que la pila estática se colme y se
cuelgue el programa.

Problema 2:
Implementación de una función recursiva que reciba un parámetro de tipo
entero y luego llame en forma recursiva con el valor del parámetro menos 1.
Programa: ejercicio312.py

def imprimir(x):
print(x)
imprimir(x-1)

imprimir(5)
Desde el bloque principal del programa se llama a la función imprimir y se le
envía el valor 5. El parámetro x recibe el valor 5. Se ejecuta el algoritmo de la
función, imprime el contenido del parámetro (5) y seguidamente se llama a una
función, en este caso a sí misma (por eso decimos que es una función
recursiva), enviándole el valor 4.
El parámetro x recibe el valor 4 y se imprime en pantalla el cuatro, llamando
nuevamente a la función imprimir enviándole el valor 3.
Si continuamos este algoritmo podremos observar que en pantalla se imprime:

5 4 3 2 1 0 -1 -2 -3 . . . . . . . . .

hasta que se bloquee el programa generándose una excepción.


Tener en cuenta que cada llamada a una función consume varios bytes por la
llamada y en este caso varios bytes por el parámetro x. Como nunca finaliza la
ejecución completa de las funciones se desborda la pila estática por las
sucesivas llamadas.

Problema 3:
Implementar una función recursiva que imprima en forma descendente de 5 a 1
de uno en uno.
Programa: ejercicio313.py

def imprimir(x):
if x>0:
print(x)
imprimir(x-1)

imprimir(5)
Ahora si podemos ejecutar este programa y observar los resultados en
pantalla. Se imprimen los números 5 4 3 2 1 y no se bloquea el programa.
Analice lo que sucede cuando el if x>0: se evalúa como falso, ¿a qué línea del
programa retorna?

Problema 4:
Imprimir los números de 1 a 5 en pantalla utilizando recursividad.
Programa: ejercicio314.py

def imprimir(x):
if x>0:
imprimir(x-1)
print(x)

imprimir(5)
Con este ejemplo se presenta una situación donde debe analizarse línea a
línea la ejecución del programa y el porque de estos resultados.
¿Por qué se imprime en pantalla 1 2 3 4 5 ?
Veamos como se apilan las llamadas recursivas:
En la primera llamada desde el bloque principal del programa el parámetro x
recibe el valor 5.

Cuando llamamos desde la misma función le enviamos el valor de x menos 1 y


la memoria queda de la siguiente forma:

Debemos entender que el parámetro x en la nueva llamada está en otra parte


de la memoria y que almacena un 4, nosotros le llamaremos x prima.
Comienza a ejecutarse la función, la condición del if se valúa como verdadero
por lo que entra al bloque y llama recursivamente a la función imprimir
pasándole el valor 3 al parámetro.

Nuevamente la condición se valúa como verdadero y llama a la función


enviándole un 2, lo mismo ocurre cuando le envía un 1 y un 0.

def imprimir(x):
if x>0:
imprimir(x-1)
print(x)

Cuando x vale 0 la condición del if se valúa como falsa y sale de la función


imprimir.
¿Qué línea ahora se ejecuta?
¿Vuelve al bloque principal y finaliza el programa? NO.
Recordemos que la última llamada de la función imprimir se había hecho desde
la misma función imprimir por lo que vuelve a la línea:

imprimir(x-1)
print(x)

Ahora si analicemos que valor tiene el parámetro x. Observemos la pila de


llamadas del gráfico:
x cuarta tiene el valor 1. Por lo que se imprime dicho valor en pantalla.
Luego de imprimir el 1 finaliza la ejecución de la función, se libera el espacio
ocupado por el parámetro x y pasa a ejecutarse la siguiente línea donde se
había llamado la función:

print(x)

Ahora x en esta instancia de la función tiene el valor 2.


Así sucesivamente hasta liberar todas las llamadas recursivas.
Es importante tener en cuenta que siempre en una función recursiva debe
haber un if para finalizar la recursividad ( en caso contrario la función recursiva
será infinita y provocará que el programa se bloquee generando una
excepción)

Problema 5:
Otro problema típico que se presenta para analizar la recursividad es el
obtener el factorial de un número.
Recordar que el factorial de un número es el resultado que se obtiene de
multiplicar dicho número por el anterior y así sucesivamente hasta llegar a uno.
Ej. el factorial de 4 es 4 * 3 * 2 * 1 es decir 24.
Programa: ejercicio315.py
Ver video

def factorial(fact):
if fact>0:
valor=fact*factorial(fact-1)
return valor
else:
return 1;

print(f"El factorial de 4 es {factorial(4)}")

La función factorial es recursiva porque desde la misma función llamamos a la


función factorial.
Debemos hacer el seguimiento del problema para analizar como se calcula.
La memoria en la primera llamada:

fact recibe el valor 4 y valor se cargará con el valor que se obtenga con el
producto de fact por el valor devuelto por la función factorial (llamada recursiva)

Nuevamente se llama recursivamente hasta que el parámetro fact reciba el


valor 0.
Cuando fact recibe un cero la condición del if se valúa como falsa y ejecuta el
else retornando un 1, la variable local de la llamada anterior a la función queda
de la siguiente manera:

Es importantísimo entender la liberación del espacio de las variables locales y


los parámetros en las sucesivas llamadas recursivas.
Por último el bloque principal recibe "valor", en este caso el valor 24.

Problema 6:
Implementar un método recursivo para ordenar los elementos de una lista.
Programa: ejercicio316.py
Ver video
def ordenar(lista, cant):
if cant>1:
for f in range(0, cant-1):
if lista[f]>lista[f + 1]:
aux=lista[f]
lista[f]=lista[f + 1]
lista[f + 1] = aux
ordenar(lista, cant - 1)

datos=[60,44,22,33,2]
print(datos)
ordenar(datos, len(datos))
print(datos)
Hasta ahora hemos visto problemas que se pueden resolver tanto con
recursividad como con estructuras repetitivas.
Es muy importante tener en cuenta que siempre que podamos emplear un
algoritmo no recursivo será mejor (ocupa menos memoria de ram y se ejecuta
más rápidamente)
Pero hay casos donde el empleo de recursividad hace mucho más sencillo el
algoritmo (tener en cuenta que no es el caso de los problemas vistos
previamente)

Retornar

91 - Recursividad: Problemas donde


conviene aplicar la recursividad
En el concepto anterior se vieron pequeños problemas para entender como
funciona la recursividad, pero no se desarrollaron problemas donde conviene
utilizar la recursividad.

Problema 1:
Recorrer un árbol de directorios en forma recursiva. Mostrar de cada directorios
los archivos y directorios, luego descender a cada directorio y hacer la misma
actividad.
Programa: ejercicio317.py
Ver video

import os

def leer(directorio):
lista = os.listdir(directorio)
for elemento in lista:
if os.path.isfile(directorio+elemento):
print(elemento+" [archivo]")
if os.path.isdir(directorio+elemento):
print(elemento+" [directorio]")
leer(directorio+elemento+"/")

leer("c:/programaspython/")
Cuando ejecutamos este programa tenemos como resultado un listado de
todos los archivos contenidos en la carpeta c:/programaspython/ y todas sus
subcarpetas:
La función leer es recursiva ya que dentro de la misma se llama a leer.
Importamos el módulo 'os':

import os

Lo primero que hacemos dentro de la función leer es llamar a la función 'listdir'


del módulo 'os' que lo que hace es retornar una lista con todos los nombres de
archivos y directorios contenidos en la carpeta que le pasamos como
parámetro (la primera vez que se llama la función leer recibe la carpeta
'c:/programaspython/'):

def leer(directorio):
lista = os.listdir(directorio)

Recorremos la lista en forma completa y por cada entrada en la lista


verificamos si se trata de un archivo:

for elemento in lista:


if os.path.isfile(directorio+elemento):
print(elemento+" [archivo]")

O si dicho elemento se trata de una carpeta, en dicha situación además de


imprimir el nombre de la carpeta procedemos a llamar en forma recursiva a la
función leer pasando como parámetro dicha carpeta para que haga la misma
actividad:

if os.path.isdir(directorio+elemento):
print(elemento+" [directorio]")
leer(directorio+elemento+"/")

Desde el bloque principal de nuestro programa llamamos por primera vez a la


función 'leer' indicando a partir de que unidad y carpeta empezar a imprimir:

leer("c:/programaspython/")

Problema 2:
Desarrollar un programa que permita recorrer un laberinto e indique si tiene
salida o no empleando la librería tkinter.
Para resolver este problema al laberinto lo representaremos con una lista de 10
elementos de tipo lista que en casa una hay 10 Label.
El valor:

0 Representa pasillo
1 Representa pared
9 Persona
5 Salida

A la salida ubicarla en la componente de la fila 9 y columna 9.


La persona comienza a recorrer el laberinto en la fila 0 y columna 0.
Los ceros y unos disponerlos en forma aleatoria.
Programa: ejercicio318.py
Ver video

import tkinter as tk
from tkinter import ttk
import random

class Aplicacion:
def __init__(self):
self.ventana1=tk.Tk()
self.ventana1.title("Laberinto")
self.salida=False
self.generar_laberinto()
self.boton1=ttk.Button(self.ventana1, tex
t="Recorrer", command=self.analizar)
self.boton1.grid(column=0, row=10, column
span=5, padx=10, pady=10)
self.boton2=ttk.Button(self.ventana1, tex
t="Generar otro", command=self.generar_otro)
self.boton2.grid(column=5, row=10, column
span=5, padx=10, pady=10)
self.ventana1.mainloop()

def generar_laberinto(self):
self.tablero=[]
listafila=[]
for fila in range(0,10):
for columna in range(0,10):
label=ttk.Label(self.ventana1, te
xt=self.retornar_aleatorio(), foreground="red")
label.grid(column=columna, row=fi
la, padx=10, pady=10)
listafila.append(label)
self.tablero.append(listafila)
listafila=[]
self.tablero[0][0].configure(text=0)
self.tablero[9][9].configure(text=5)
def generar_otro(self):
for fila in range(0,10):
for columna in range(0,10):
self.tablero[fila][columna].confi
gure(text=self.retornar_aleatorio(),background="#
f0f0f0")
self.tablero[0][0].configure(text=0)
self.tablero[9][9].configure(text=5)

def retornar_aleatorio(self):
valor=random.randint(1,4)
if valor==1:
return 1
else:
return 0

def analizar(self):
self.salida=False
self.recorrer(0,0)
if self.salida:
self.ventana1.title("Tiene salida el
laberinto")
else:
self.ventana1.title("No tiene salida
el laberinto")

def recorrer(self, fil, col):


if fil>=0 and fil<10 and col>=0 and col<1
0 and self.salida==False:
if self.tablero[fil][col].cget("text"
)==5:
self.salida=True
else:
if self.tablero[fil][col].cget("t
ext")==0:
self.tablero[fil][col].config
ure(text=9)
self.tablero[fil][col].config
ure(background="yellow")
self.recorrer(fil,col+1)
self.recorrer(fil+1,col)
self.recorrer(fil-1,col)
self.recorrer(fil,col-1)

aplicacion1=Aplicacion()
Cuando ejecutamos el programa se genera un laberinto en forma aleatoria:
Cuando presionamos el botón "Recorrer" comenzamos a avanzar desde la fila
0 y columna 0:
En el método generar_laberinto mediante dos for anidados procedemos a crear
cada uno de los objetos de tipo Label y almacenarlos en una lista:

def generar_laberinto(self):
self.tablero=[]
listafila=[]
for fila in range(0,10):
for columna in range(0,10):
label=ttk.Label(self.ventana1, text=self.retornar_aleatorio(), f
oreground="red")
label.grid(column=columna, row=fila, padx=10, pady=10)
listafila.append(label)

Cada vez que finaliza el for interno procedemos a almacenar en el atributo


self.tablero la lista que acabamos de crear con las 10 Label:

self.tablero.append(listafila)
listafila=[]

Fuera de los for configuramos el inicio del laberinto con un valor 0 (pasillo) y el
valor 5 para la salida del laberinto:

self.tablero[0][0].configure(text=0)
self.tablero[9][9].configure(text=5)

Cuando se presiona el botón para recorrer el laberinto se llama al método


'analizar' donde inicializamos el atributo 'salida' con el valor False
presuponiendo que no tiene salida el laberinto:

def analizar(self):
self.salida=False
self.recorrer(0,0)
if self.salida:
self.ventana1.title("Tiene salida el laberinto")
else:
self.ventana1.title("No tiene salida el laberinto")

En el método 'analizar' llamamos al método recursivo 'recorrer' y lo


comenzamos en la fila 0 y columna 0.
El método recursivo como vemos puede hacer múltiples llamadas recursivas:
def recorrer(self, fil, col):
if fil>=0 and fil<10 and col>=0 and col<10 and self.salida==False:
if self.tablero[fil][col].cget("text")==5:
self.salida=True
else:
if self.tablero[fil][col].cget("text")==0:
self.tablero[fil][col].configure(text=9)
self.tablero[fil][col].configure(background="yellow")
self.recorrer(fil,col+1)
self.recorrer(fil+1,col)
self.recorrer(fil-1,col)
self.recorrer(fil,col-1)

En el método 'recorrer' lo primero que verificamos que la coordenada a visitar


esté dentro del tablero y que no hayamos encontrado la salida:

if fil>=0 and fil<10 and col>=0 and col<10 and self.salida==False:

Si el primer if se verifica verdadero pasamos a ver si en esa coordenada se


encuentra la salida:

if self.tablero[fil][col].cget("text")==5:
self.salida=True

En caso de que no se encuentre la salida verificamos si estamos en una


coordenada que hay pasillo:

else:
if self.tablero[fil][col].cget("text")==0:

En el caso que haya pasillo en dicha coordenada fijamos la persona


disponiendo un 9 y cambiamos el color de fondo de dicha Label:

self.tablero[fil][col].configure(text=9)
self.tablero[fil][col].configure(background="yellow")

Finalmente tratamos de avanzar en las cuatro direcciones para seguir


buscando la salida:

self.recorrer(fil,col+1)
self.recorrer(fil+1,col)
self.recorrer(fil-1,col)
self.recorrer(fil,col-1)

Problema 3:
Desarrollar el juego del Buscaminas. Definir una lista de 10 elementos de tipo
lista y en estas listas internas almacenar las referencias a botones.
El juego consiste en destapar todas las casillas que no tiene bombas. Si se
presiona la casilla que tiene bomba finaliza el juego. En las casillas que están
en el perímetro de una bomba aparece un número que indica la cantidad de
bombas a su alrededor. Por ejemplo si una casilla tiene el 2 significa que de las
8 casillas a su alrededor hay 2 bombas.
Si se selecciona una casilla que no tiene bombas a su alrededor se libera esta
y todas las que se encuentran próximas a ella.
Permitir volver a jugar mediante un menú de opciones.
Cuando se inicia el juego debe aparecer el tablero con las 100 casillas:
Luego de destapar algunas casillas:
Programa: ejercicio319.py
Ver video

import tkinter as tk
from tkinter import ttk
import random
from tkinter import messagebox as mb

class Aplicacion:
def __init__(self):
self.ventana1=tk.Tk()
self.destapadas=0
self.enjuego=True
self.ventana1.geometry("500x500")
self.ventana1.title("Buscaminas")
self.ventana1.configure(background="#BEF7
81")
self.generar_tablero()
self.generar_bombas()
self.generar_bombas_proximas()
menubar1 = tk.Menu(self.ventana1)
self.ventana1.config(menu=menubar1)
opciones1 = tk.Menu(menubar1)
opciones1.add_command(label="Reiniciar",
command=self.reiniciar)
opciones1.add_command(label="Salir", comm
and=self.ventana1.destroy)
menubar1.add_cascade(label="Opciones", me
nu=opciones1)
self.ventana1.mainloop()

def generar_tablero(self):
self.tablero=[]
listafila=[]
for fila in range(0,10):
for columna in range(0,10):
boton=ttk.Button(self.ventana1, t
ext="", command=lambda fi=fila, co=columna: self.
presion(fi,co))
boton.place(x=columna*50,y=fila*5
0,width=50,height=50)
listafila.append(boton)
self.tablero.append(listafila)
listafila=[]

def generar_bombas(self):
self.bombas=[]
listafila=[]
for fila in range(0,10):
for columna in range(0,10):
listafila.append("0")
self.bombas.append(listafila)
listafila=[]
cantidad=10
while cantidad!=0:
fila=random.randint(0,9)
columna=random.randint(0,9)
if self.bombas[fila][columna]!="b":
self.bombas[fila][columna]="b"
#self.tablero[fila][columna].conf
igure(text="b")
cantidad=cantidad-1

def generar_bombas_proximas(self):
for f in range(0,10):
for c in range(0,10):
if self.bombas[f][c]=="0":
cant=self.contar_lado(f,c)
self.bombas[f][c]=str(cant)

def contar_lado(self, fila, columna):


total=0
if fila-1>=0 and columna-1>=0:
if self.bombas[fila-1][columna-1]=="b
":
total=total+1
if fila-1>=0:
if self.bombas[fila-1][columna]=="b":
total=total+1
if fila-1>=0 and columna+1<10:
if self.bombas[fila-1][columna+1]=="b
":
total=total+1
if columna+1<10:
if self.bombas[fila][columna+1]=="b":
total=total+1
if fila+1<10 and columna+1<10:
if self.bombas[fila+1][columna+1]=="b
":
total=total+1
if fila+1<10:
if self.bombas[fila+1][columna]=="b":
total=total+1
if fila+1<10 and columna-1>=0:
if self.bombas[fila+1][columna-1]=="b
":
total=total+1
if columna-1>=0:
if self.bombas[fila][columna-1]=="b":
total=total+1
return total

def presion(self, fila, columna):


if self.enjuego:
if self.bombas[fila][columna]=="b":
self.enjuego=False
self.destapar()
mb.showinfo("Información", "Perdi
ste hay una bomba")
else:
if int(self.bombas[fila][columna]
)==0:
self.recorrer(fila,columna)
else:
if int(self.bombas[fila][colu
mna])>=1 and int(self.bombas[fila][columna])<=8 a
nd self.tablero[fila][columna].cget("text")=="":
self.tablero[fila][column
a].configure(text=self.bombas[fila][columna])
self.destapadas=self.dest
apadas+1
if self.destapadas==90:
self.enjuego=False
mb.showinfo("Información", "Ganas
te")
def recorrer(self, fil, col):
if fil>=0 and fil<10 and col>=0 and col<1
0:
if self.bombas[fil][col]=="0" and sel
f.tablero[fil][col]!=None:
self.bombas[fil][col]=" "
self.destapadas=self.destapadas+1
self.tablero[fil][col].destroy()
self.tablero[fil][col]=None
self.recorrer (fil, col + 1)
self.recorrer (fil, col - 1)
self.recorrer (fil + 1, col)
self.recorrer (fil - 1, col)
self.recorrer (fil - 1, col - 1)
self.recorrer (fil - 1, col + 1)
self.recorrer (fil + 1, col + 1)
self.recorrer (fil + 1, col - 1)
else:
if self.tablero[fil][col]!=None:
if int(self.bombas[fil][col])
>=1 and int(self.bombas[fil][col])<=8 and self.ta
blero[fil][col].cget("text")=="":
self.tablero[fil][col].co
nfigure(text=self.bombas[fil][col])
self.destapadas=self.dest
apadas+1
def reiniciar(self):
self.destapadas=0
self.eliminar_botones()
self.generar_tablero()
self.generar_bombas()
self.generar_bombas_proximas()
self.enjuego=True

def eliminar_botones(self):
for fila in range(0,10):
for columna in range(0,10):
if self.tablero[fila][columna]!=N
one:
self.tablero[fila][columna].d
estroy()
self.tablero[fila][columna]=N
one

def destapar(self):
for fila in range(0,10):
for columna in range(0,10):
if self.tablero[fila][columna]!=N
one:
if self.bombas[fila][columna]
!="0":
self.tablero[fila][column
a].configure(text=self.bombas[fila][columna])
aplicacion1=Aplicacion()
La recursividad en este problema se utiliza cuando hay que destapar casillas
libres a su alrededor en el método recorrer.

Retornar

92 - Funciones de orden superior


Python es un lenguaje multiparadigma: permite programación estructurada,
orientado a objetos y también introduce características existentes en los
lenguajes funcionales que nos dejan crear un código más claro y expresivo.
Una de las características del paradigma de la programación funcional son las
funciones de orden superior.
Las funciones de orden superior son funciones que pueden recibir como
parámetros otras funciones y/o devolverlas como resultados.
Veremos una serie de ejemplos muy sencillos para ver como Python
implementa el concepto de funciones de orden superior y a medida que
avancemos en el curso podremos ver las ventajas de este paradigma.

Problema 1
Definir una función de orden superior llamada operar. Llegan como parámetro
dos enteros y una función. En el bloque de la función llamar a la función que
llega como parámetro y enviar los dos primeros parámetros.
La función retorna un entero.
Programa: ejercicio320.py
Ver video

def operar(v1,v2,fn):
return fn(v1,v2)

def sumar(x1,x2):
return x1+x2

def restar(x1,x2):
return x1-x2

def multiplicar(x1,x2):
return x1*x2

def dividir(x1,x2):
return x1/x2

resu1=operar(10,3,sumar)
print(resu1)

resu2=operar(10,3,restar)
print(resu2)

print(operar(30,10,multiplicar))

print(operar(10,2,dividir))
Tenemos definidas 5 funciones en este problema. La única función de orden
superior es la llamada "operar":

def operar(v1,v2,fn):
return fn(v1,v2)

El tercer parámetro de esta función se llama "fn" y es de tipo función.


El algoritmo de la función operar consiste en llamar a la función fn y pasar los
dos valores que espera dicha función:
return fn(v1,v2)

Como la función operar retorna un valor debemos indicar con la palabra clave
return que devuelva el dato que a su vez retorna la función "fn".
Las cuatro funciones que calculan la suma, resta, multiplicación y división no
tienen nada nuevo a lo visto en conceptos anteriores:

def sumar(x1,x2):
return x1+x2

def restar(x1,x2):
return x1-x2

def multiplicar(x1,x2):
return x1*x2

def dividir(x1,x2):
return x1/x2

En el bloque principal de nuestro programa llamamos a la función operar y le


pasamos tres datos, dos enteros y uno con la referencia de una función:

resu1=operar(10,3,sumar)
print(resu1)

Como vemos para pasar la referencia de una función solo indicamos su


nombre.
La función operar retorna un entero y lo almacenamos en la variable resu1 que
mostramos luego por pantalla:

print(resu1)

Es importante imaginar el funcionamiento de la función operar que recibe tres


datos y utiliza uno de ellos para llamar a otra función que retorna un valor y que
luego este valor lo retorna operar y llega finalmente a la variable "resu1".
Llamamos a operar y le pasamos la referencia a la función restar:

resu2=operar(10,3,restar)
print(resu2)
De forma similar llamamos a operar y le pasamos las referencias a las otras
funciones:

print(operar(30,10,multiplicar))

print(operar(10,2,dividir))

Tener en cuenta que para sumar dos valores es mejor llamar directamente a la
función sumar y pasar los dos valores, pero el objetivo de este problema es
conocer la sintaxis de las funciones de orden superior presentando el problema
más sencillo posible.
Las funciones de orden superior se pueden utilizar perfectamente en los
métodos de una clase.

Problema 2
Declarar una clase que almacene el nombre y la edad de una persona. Definir
un método que retorne True o False según si la persona es mayor de edad o
no. Este método debe recibir como parámetro una función que al llamarla
pasando la edad de la persona retornará si es mayor o no de edad.
Tener en cuenta que una persona es mayor de edad en Estados Unidos si
tiene 21 o más años y en Argentina si tiene 18 o más años.
Programa: ejercicio321.py
Ver video

class Persona:
def __init__(self,nombre,edad):
self.nombre=nombre
self.edad=edad

def es_mayor(self,fn):
return fn(self.edad)

def mayor_estadosunidos(edad):
if edad>=21:
return True
else:
return False

def mayor_argentina(edad):
if edad>=18:
return True
else:
return False

persona1=Persona("juan", 18)
if persona1.es_mayor(mayor_argentina):
print(f"{persona1.nombre} es mayor si vive en
Argentina")
else:
print(f"{persona1.nombre} no es mayor si vive
en Argentina")
if persona1.es_mayor(mayor_estadosunidos):
print(f"{persona1.nombre} es mayor si vive en
Estados Unidos")
else:
print(f"{persona1.nombre} no es mayor si vive
en Estados Unidos")
Declaramos la clase Persona con dos propiedades llamadas nombre y edad:

class Persona:
def __init__(self,nombre,edad):
self.nombre=nombre
self.edad=edad

La clase persona por si misma no guarda la nacionalidad de la persona, en


cambio cuando se pregunta si es mayor de edad se le pasa como referencia
una función que al pasar la edad nos retorna true o false:

def es_mayor(self,fn):
return fn(self.edad)

Tenemos dos funciones que al pasar una edad nos retornan si es mayor de
edad o no:

def mayor_estadosunidos(edad):
if edad>=21:
return True
else:
return False

def mayor_argentina(edad):
if edad>=18:
return True
else:
return False

En el bloque principal del programa creamos un objeto de la clase persona:

persona1=Persona("juan", 18)

Llamamos al método es_mayor del objeto persona1 y le pasamos la referencia


de la función "mayor_argentina":

if persona1.es_mayor(mayor_argentina):
print(f"{persona1.nombre} es mayor si vive en Argentina")
else:
print(f"{persona1.nombre} no es mayor si vive en Argentina")

Ahora llamamos al método es_mayor pero pasando la referencia de la función


"mayor_estadosunidos":

if persona1.es_mayor(mayor_estadosunidos):
print(f"{persona1.nombre} es mayor si vive en Estados Unidos")
else:
print(f"{persona1.nombre} no es mayor si vive en Estados Unidos")

Como podemos comprobar el concepto de funciones de orden superior es


aplicable a los métodos de una clase.

Retornar

93 - Funciones lambda en Python


Una función lambda es cuando enviamos a una función de orden superior
directamente una función anónima.
Es más común enviar una expresión lambda en lugar de enviar la referencia de
una función como vimos en el concepto anterior.

Problema 1
Definir una función de orden superior llamada operar. Llegan como parámetro
dos enteros y una función. En el bloque de la función llamar a la función que
llega como parámetro y enviar los dos primeros parámetros.
Desde el bloque principal llamar a operar y enviar distintas expresiones
lambdas que permitan sumar, restar, multiplicar y dividir .
Programa: ejercicio322.py
Ver video

def operar(v1,v2,fn):
return fn(v1,v2)

resu1=operar(10,3,lambda x1,x2: x1+x2)


print(resu1)

resu2=operar(10,3,lambda x1,x2: x1-x2)


print(resu2)

print(operar(30,10,lambda x1,x2: x1*x2))

print(operar(10,2,lambda x1,x2: x1/x2))


La función de orden superior operar es la que vimos en el concepto anterior:

def operar(v1,v2,fn):
return fn(v1,v2)

La primer expresión lambda podemos identificarla en la primer llamada a la


función operar:

resu1=operar(10,3,lambda x1,x2: x1+x2)


print(resu1)

Una expresión lambda comienza por la palabra clave 'lambda' y está


compuesta por una serie de parámetros (en este caso x1 y x2), el signo ':' y el
cuerpo de la función:

x1+x2

El nombre de los parámetros se llaman x1 y x2, pero podrían tener cualquier


nombre:

resu1=operar(10,3,lambda valor1,valor2: valor1+valor2)

Se infiere que la suma de x1 y x2 es el valor a retornar.


La segunda llamada a operar le pasamos una expresión lambda similar a la
primer llamada:

resu2=operar(10,3,lambda x1,x2: x1-x2)


print(resu2)

Las otras dos llamadas son iguales:

print(operar(30,10,lambda x1,x2: x1*x2))

print(operar(10,2,lambda x1,x2: x1/x2))


Problema 2
Confeccionar una función de orden superior que reciba una lista que almacena
valores enteros y una función con un parámetro entero y que retorne un
boolean.
La función debe analizar cada elemento de la lista llamando a la función que
recibe como parámetro, si retorna un True se pasa a mostrar el elemento.
En el bloque principal definir una lista de enteros.
Imprimir de la lista:

• Los valores múltiplos de 2

• Los valores múltiplos de 3 o de 5

• Los valores mayores o iguales a 50

• Los valores comprendidos entre 1 y 50 o entre 70 y 100.

Programa: ejercicio323.py
Ver video

def imprimir_si(lista, fn):


for elemento in lista:
if fn(elemento):
print(elemento)

lista1=[9, 20, 70, 60, 19]


print("Valores pares de la lista")
imprimir_si(lista1, lambda x: x%2==0)
print("Valores múltiplos de 3 o de 5")
imprimir_si(lista1, lambda x: x%3==0 or x%5==0)
print("Imprimir valores mayores o iguales a 50")
imprimir_si(lista1, lambda x: x>=50)
print("Imprimir los valores comprendidos entre 1
y 50 o 70 y 100")
imprimir_si(lista1, lambda x: x>=1 and x<=50 or x
>=70 and x<=100)
print("Imprimir la lista completa")
imprimir_si(lista1, lambda x: True )
La función de orden superior 'imprimir_si' recibe una lista y una función:

def imprimir_si(lista, fn):

Dentro de la función recorremos los elementos de la lista y llamamos a la


función que recibe como parámetro para cada elemento de la lista, si retorna
un True pasamos a mostrar el valor:

for elemento in lista:


if fn(elemento):
print(elemento)

La ventaja de la función 'imprimir_si' es que podemos utilizarla para resolver


una gran cantidad de problemas, solo debemos pasar una expresión lambda
que analice cada entero que recibe.
En el bloque principal creamos la lista y cargamos 5 valores:

lista1=[9, 20, 70, 60, 19]

Para imprimir los valores múltiplos de 2 nuestra expresión lambda recibe un


parámetro llamado 'x' y el algoritmo que verifica si es par o no consiste en
verificar si el resto de dividirlo por 2 es cero:

print("Valores múltiplos de 2")


imprimir_si(lista1, lambda x: x%2==0)

Es importante entender que nuestra expresión lambda no tiene una estructura


repetitiva, sino que desde la función 'imprimir_si' llamará a esta función
anónima tantas veces como elementos tenga la lista.
El algoritmo de la función varía si queremos identificar si el número es múltiplo
de 3 o de 5:

print("Valores múltiplos de 3 o de 5")


imprimir_si(lista1, lambda x: x%3==0 or x%5==0)

Para imprimir todos los valores mayores o iguales a 50 debemos verificar si el


parámetro x es >= 50:

print("Imprimir valores mayores o iguales a 50")


imprimir_si(lista1, lambda x: x>=50)

Para analizar si la componente se encuentra en distintos rangos:

print("Imprimir los valores comprendidos entre 1 y 50 o 70 y 100")


imprimir_si(lista1, lambda x: x>=1 and x<=50 or x>=70 and x<=100)

Previo al if indicamos el valor a retornar si la condición del if se verifica


verdadero y en el caso contrario por el else indicamos el otro valor.
En forma muy sencilla si queremos imprimir todo el arreglo retornamos para
cada elemento que analiza nuestra expresión lambda el valor True:

print("Imprimir la lista completa")


imprimir_si(lista1, lambda x: True )

Este es un problema donde ya podemos notar las potencialidades de las


funciones de orden superior y las expresiones lambdas que le pasamos a las
mismas.

Problema 3
Confeccionar una función de orden superior que reciba un String y una función
con un parámetro de tipo String que retorna un Boolean.
La función debe analizar cada elemento del String llamando a la función que
recibe como parámetro, si retorna un True se agrega dicho caracter al String
que se retornará.
En el bloque principal definir un String con una cadena cualquiera.
Llamar a la función de orden superior y pasar expresiones lambdas para filtrar
y generar otro String con las siguientes restricciones:

• Un String solo con las vocales

• Un String solo con los caracteres en minúsculas

• Un String con todos los caracteres no alfabéticos


Programa: ejercicio324.py
Ver video

def filtrar(cadena,fn):
cad=""
for caracter in cadena:
if fn(caracter):
cad=cad+caracter
return cad

cadena="¿Esto es la prueba 1 o la prueba 2?"


print("String original")
print(cadena)
print("String solo con las vocales")
cadena2=filtrar(cadena, lambda car: car == 'a' or
car == 'e' or car == 'i' or car == 'o' or car ==
'u'
or car == 'A'
or car == 'E' or car == 'I' or car == 'O' or car
== 'U')
print(cadena2)

print("String solo con los caracteres en minúscul


a")
cadena3=filtrar(cadena, lambda car: car >='a' and
car <= 'z')
print(cadena3)
print("String solo con los caracteres no alfabéti
cos")
cadena3=filtrar(cadena, lambda car: not(car >='a'
and car <= 'z') and not(car >='A' and car <= 'Z')
)
print(cadena3)
Nuestra función de orden superior se llama filtrar y recibe un String y una
función:

def filtrar(cadena,fn):

El algoritmo de la función filtrar consiste en recorrer el String que llega como


parámetro y llamar a la función fn que es la que informará si el caracter
analizado debe formar parte del String final a retornar.

cad=""
for caracter in cadena:
if fn(caracter):
cad=cad+caracter
return cad

En el bloque principal definimos un String con una cadena cualquiera:

cadena="¿Esto es la prueba 1 o la prueba 2?"


print("String original")
print(cadena)

La primer llamada a la función de orden superior la hacemos enviando una


expresión lambda que considere parte del String a generar solo las vocales
minúsculas y mayúsculas:

print("String solo con las vocales")


cadena2=filtrar(cadena, lambda car: car == 'a' or car == 'e' or car == 'i' or ca
r == 'o' or car == 'u'
or car == 'A' or car == 'E' or car == 'I' or
car == 'O' or car == 'U')
print(cadena2)
Para generar un String solo con las letras minúsculas debemos verificar si el
parámetro de la función anónima se encuentra en el rango 'a' y 'z':

print("String solo con los caracteres en minúscula")


cadena3=filtrar(cadena, lambda car: car >='a' and car <= 'z')
print(cadena3)

Por último para recuperar todos los símbolos que no sean letras expresamos la
siguiente condición:

print("String solo con los caracteres no alfabéticos")


cadena3=filtrar(cadena, lambda car: not(car >='a' and car <= 'z') and not(car >=
'A' and car <= 'Z'))
print(cadena3)

Con este problema podemos seguir apreciando las grandes ventajas que nos
proveen las expresiones lambdas para la resolución de algoritmos.

Retornar

94 - Comprensión de listas en Python


Ver video
La comprensión de listas es una construcción en Python que nos permite crear
listas a partir de otras listas, tuplas y cualquier iterable.
Nos permite escribir en forma más concisa un algoritmo. Veamos con un
ejemplo como lo resolvemos con y sin comprensión de listas.

Problema 1
Definir una lista con 5 valores enteros, luego a partir de la primer lista generar
una segunda lista con los valores elevados al cuadrado.
Programa: ejercicio325.py

lista1=[8, 5, 4, 10, 2]
lista2=[]
for elemento in lista1:
lista2.append(elemento*elemento)
print("Lista 1")
print(lista1)
print("Nueva lista")
print(lista2)
Mediante la construcción de comprensión de listas tenemos:
Programa: ejercicio326.py

lista1=[8, 5, 4, 10, 2]
lista2=[elemento*elemento for elemento in lista1]
print("Lista 1")
print(lista1)
print("Nueva lista")
print(lista2)
Como vemos lo resolvemos en una sola línea:

lista2=[elemento*elemento for elemento in lista1]

Lo que hacíamos en 3 líneas:

lista2=[]
for elemento in lista1:
lista2.append(elemento*elemento)

La sintaxis para la comprensión de listas requiere disponer un ciclo repetitivo a


la derecha 'for elemento in lista1' y el valor a generar a la izquierda
'elemento*elemento':

lista2=[elemento*elemento for elemento in lista1]

Esta construcción para el recorrido de iterables se ejecuta más rápido que la


forma tradicional. Requiere un poco de tiempo para adaptar nuestro
razonamiento a la nueva sintaxis.
Problema 2
Se tiene una lista con un conjunto de tuplas con los nombres y edades de
personas:

personas=[('pedro',33),('ana',3),('juan',13),('carla',45)]

Generar una lista con las personas mayores de edad.


Programa: ejercicio327.py

personas=[('pedro',33),('ana',3),('juan',13),('ca
rla',45)]
personas_mayores=[per for per in personas if per[
1]>=18]
print(personas_mayores)
Mediante el for recuperamos cada persona en la nueva lista si su edad es
mayor o igual a 18:

personas_mayores=[per for per in personas if per[1]>=18]

Problema 3
Generar una lista con todos los valores múltiplos de 8 comprendidos entre 1 y
500.
Programa: ejercicio328.py

multiplos8=[valor for valor in range(1,501) if va


lor%8==0]
print(multiplos8)
Disponemos un for que recorre los valores del 1 al 500 inclusive, cada vez que
el resto de dividir dicho valor por 8 se verifica verdadero procedemos a guardar
dicho valor en la lista 'multiplos8'.

Varios for
Podemos utilizar más de un for cuando empleamos la característica de 'List
Comprehensions' de Python.

Problema 4
Se tiene una lista de nombres de personas. Generar otra lista cuyos elementos
sean a su vez listas con dos nombres cada uno.
Tener en cuenta que nunca se debe combinar el mismo nombre dos veces.
Programa: ejercicio329.py
Ver video

nombres=['juan','pablo','luis','mauro','hector']
nombres_compuestos=[[nombre1,nombre2] for nombre1
in nombres for nombre2 in nombres if nombre1!=nom
bre2]
print(nombres_compuestos)
Podemos comprobar que conciso ha quedado el algoritmo para generar pares
de nombres:
Si analizamos:

nombres_compuestos=[[nombre1,nombre2] for nombre1 in nombres for nombre2 in nomb


res if nombre1!=nombre2]

Cada vez que la condición del if se verifica verdadera: 'if nombre1!=nombre2'


se genera una lista con los dos nombres: '[nombre1,nombre2]'.
Como tenemos dos estructuras for cada vez que de ejecuta el for interno
completamente avanza uno el for externo: 'for nombre1 in nombres for
nombre2 in nombres'.
El mismo algoritmo pero sin utilizar 'List Comprehensions' es:

nombres=['juan','pablo','luis','mauro','hector']
nombres_compuestos=[]
for nombre1 in nombres:
for nombre2 in nombres:
if nombre1!=nombre2:
nombres_compuestos.append([nombre1,nombre2])
print(nombres_compuestos)

Requiere tiempo para habituarse a las 'List Comprehensions', pero una vez que
le tomamos la mano podemos obtener grandes ventajas en la definición de
algoritmos muy breves.
Vamos a resolver un problema clásico que a muchos programadores le han
hecho en su primer entrevista para un puesto de programador.

Problema 5
Codificar un programa que muestre en pantalla los números del 1 al 100,
sustituyendo los múltiplos de 3 por el palabra "Fizz" y, a su vez, los múltiplos de
5 por "Buzz". Para los números que, al tiempo, son múltiplos de 3 y 5, mostrar
el mensaje "FizzBuzz".
Programa: ejercicio330.py
Ver video

for nro in range(1,101):


if nro%3==0 and nro%5==0:
print("FizzBuzz")
elif nro%3==0:
print("Fizz")
elif nro%5==0:
print("Buzz")
else:
print(nro)
Ahora la solución de este problema empleando 'List Comprehensions'.
Programa: ejercicio330.py

print(["Fizz"*(not nro%3) + "Buzz"*(not nro%5) or


nro for nro in range(1, 101)])
Con una única línea tenemos tenemos una lista con la secuencia que pide el
problema:
Retornar

95 - Estructura de datos tipo conjunto


(set)
Ver video
Hemos visto en conceptos anteriores las estructuras de datos que vienen por
defecto en Python y hacen a la esencia de este lenguaje:

• Listas

• Tuplas

• Diccionarios

La cuarta estructura de datos que presentaremos se llama conjunto (set), esta


estructura de datos permite almacenar una colección de elementos que no se
pueden repetir y no se encuentran ordenados.
Creación de un conjunto por asignación
Para crear un conjunto por asignación debemos indicar sus elementos
encerrados entre llaves y separados por coma.

conjunto1={1, 5, 10, 20}


print(conjunto1)

Los elementos de un conjunto pueden ser de distinto tipo:

conjunto2={"juan", 20, 6.4, True}


print(conjunto2)

Podemos definir elementos de un conjunto de tipo tupla pero no de tipo lista,


diccionario o conjunto:

conjunto3={("juan", 33), ("ana", 44)}


print(conjunto3)

Agregar y eliminar elementos de un conjunto.


Mediante el método add agregamos un elemento a un conjunto, si el valor ya
existe luego no se inserta:

lenguajes={"C", "Pascal", "PHP", "Python"}


print(lenguajes) # {"C", "Pascal", "PHP", "Python"}
lenguajes.add("Ruby")
print(lenguajes) # {"C", "Pascal", "PHP", "Python, "Ruby"}
lenguajes.add("PHP")
print(lenguajes) # {"C", "Pascal", "PHP", "Python, "Ruby"}

El conjunto "lenguajes" se crea con 4 elementos. Luego se agrega un quinto


elemento:

lenguajes.add("Ruby")

Si intentamos agregar un elemento que ya existe el mismo no se agrega y no


genera error:

lenguajes.add("PHP")

Para eliminar un elemento de un conjunto debemos llamar al método "remove":


lenguajes={"C", "Pascal", "PHP", "Python"}
print(lenguajes)
lenguajes.remove("Pascal")
print(lenguajes)

Si el método remove no encuentra el elemento dentro del conjunto genera una


excepción de tipo "KeyError".
Si queremos eliminar un elemento del conjunto y que no genere error si no
existe debemos hacer uso del método "discard":

lenguajes={"C", "Pascal", "PHP", "Python"}


print(lenguajes)
lenguajes.discard("Kotlin")
print(lenguajes)

Operador de pertenencia 'in'.


Si queremos verificar si un conjunto contiene un determinado valor podemos
utilizar el operador 'in':

lenguajes={"C", "Pascal", "PHP", "Python"}


if "PHP" in lenguajes:
print("El lenguaje PHP se encuentra en el conjunto")
else:
print("El lenguaje PHP no se encuentra en el conjunto")

La estructura condicional if se verifica verdadero debido a que la cadena "PHP"


se encuentra contenido en el conjunto "lenguajes".

Operaciones con conjuntos.


Las operaciones básicas con conjuntos son:

• Unión

• Intersección

• Diferencia

• Diferencia simétrica
Gráficamente estas operaciones con dos conjuntos las podemos graficar:

Problema 1
Definir dos conjuntos que almacenen cada uno una serie de lenguajes de
programación. Efectuar las cuatro operaciones básicas con dichos conjuntos.
Programa: ejercicio331.py
Ver video

lenguajes1={"C", "Pascal", "PHP", "Python"}


lenguajes2={"C++", "Java", "Python"}
print("Lenguajes estructurados")
print(lenguajes1)
print("Lenguajes orientados a objetos")
print(lenguajes2)
conjunto1=lenguajes1 | lenguajes2
print("Todos los lenguajes (Unión)")
print(conjunto1)
conjunto2=lenguajes1 & lenguajes2
print("Intersección de los dos conjuntos de lengu
ajes (Intersección)")
print(conjunto2)
conjunto3=lenguajes1 - lenguajes2
print("Diferencia de los dos conjuntos de lenguaj
es (Diferencia)")
print(conjunto3)
conjunto4=lenguajes1 ^ lenguajes2
print("lenguajes del conjunto lenguajes1 o del co
njunto lenguajes2 pero no en ambos (Diferencia si
métrica)")
print(conjunto4)
Los operadores de conjuntos son:

| (unión)
& (Intersección)
- (Diferencia)
^ (Diferencia simétrica)

Como resultado de ejecutar este programa tenemos:


En lugar de utilizar los operadores de conjuntos podemos llamar a sus métodos
y obtener el mismo resultado:

lenguajes1={"C", "Pascal", "PHP", "Python"}


lenguajes2={"C++", "Java", "Python"}
print("Lenguajes estructurados")
print(lenguajes1)
print("Lenguajes orientados a objetos")
print(lenguajes2)
x=lenguajes1.union(lenguajes2)
print("Todos los lenguajes")
print(x)
x=lenguajes1.intersection(lenguajes2)
print("Intersección de los dos conjuntos de lenguajes")
print(x)
x=lenguajes1.difference(lenguajes2)
print("Diferencia de los dos conjuntos de lenguajes")
print(x)
x=lenguajes1.symmetric_difference(lenguajes2)
print("lenguajes del conjunto lenguajes1 o del conjunto lenguajes2 pero no en am
bos")
print(x)

Conjuntos disjuntos.
Dos conjuntos son disjuntos si no tienen elementos en común entre ellos. Su
intersección es el conjunto vacío.
La clase set dispone del método 'isdisjoint' que retorna True si los conjuntos no
tienen elementos en común:

dias_feriados={"sábado","domingo"}
dias_laborables={"lunes", "martes", "miércoles","jueves","viernes"};
if dias_laborables.isdisjoint(dias_feriados):
print("dias_laborables no tiene elementos en común con dias_feriados")

Estos dos conjuntos no tiene elementos en común, luego el if se verifica


verdadero.

Igualdad de conjuntos, subconjuntos y superconjuntos.


En Python podemos utilizar los operadores:

• conjunto1==conjunto2

• conjunto1!=conjunto2

• conjunto1<conjunto2 (si el conjunto1 es un subconjunto de conjunto2)

• conjunto1<=conjunto2 (si el conjunto1 es un subconjunto o es igual que


conjunto2)

• conjunto1>conjunto2 (si el conjunto1 es un superconjunto de conjunto2)


• conjunto1>=conjunto2 (si el conjunto1 es un superconjunto o es igual
que conjunto2)

Algunos ejemplos empleando estos operadores:

dias_semana={"lunes", "martes", "miércoles","jueves","viernes","sábado","domingo


"}
dias_feriados={"sábado","domingo"}
dias_laborables={"lunes", "martes", "miércoles","jueves","viernes"}
if dias_feriados<dias_semana:
print("dias_feriados es un subconjunto de dias_semana")
if dias_feriados!=dias_laborables:
print("dias_feriados es distinto a dias_laborables")
if dias_semana>dias_laborables:
print("dias_semana es un superconjunto de dias_laborables")

Acotaciones.
• Para conocer la cantidad de elementos de un conjunto disponemos de la
función 'len':

• lenguajes={"C", "Pascal", "PHP", "Python"}

• print(len(lenguajes)) # imprime un 4

• Para crear un conjunto vacío debemos llamar a la función 'set':

• lenguajes=set()
• lenguajes.add("C")

• lenguajes.add("Pascal")

• lenguajes.add("PHP")

• lenguajes.add("Python")

• print(len(lenguajes)) # imprime un 4

Es importante recordar que en Python las llaves abiertas y cerradas


crean un diccionario y no un conjunto:

productos={}
productos["manzanas"]=39
productos["peras"]=32
productos["lechuga"]=17
print(productos)

• Un uso común de los conjuntos es eliminar los valores repetidos de listas


y tuplas:

• edades=[23, 21, 25, 21, 23]

• print(edades)

• conjunto=set(edades)

• print(conjunto) # 25, 21, 23

Se crea un conjunto llamando a set y pasando como parámetro una lista,


luego el conjunto no almacena los valores repetidos de la lista.
• Podemos iterar un conjunto mediante la estructura repetitiva for:

• dias={"lunes", "martes", "miércoles"}

• for dia in dias:

• print(dia)

Conjuntos congelados 'frozenset'


Hay otra clase llamada 'frozenset' que permite crear conjuntos inmutables, es
decir que no se le pueden agregar o eliminar elementos una vez creado.

Problema 2
Realizar la carga de valores enteros y sumarlos, cada vez que se ingresa un
valor preguntar al operador si desea ingresar otro valor.
Programa: ejercicio332.py
Ver video

opciones_salir=frozenset(["no","NO"])
suma=0
while True:
valor=int(input("Ingrese un valor:"))
suma=suma+valor
op=input("Desea ingresar otro valor: [si/no]"
)
if op in opciones_salir:
break
print(f"La suma de los valores es {suma}")
Creamos un conjunto inmutable con las dos opciones que finalizarán la carga
de valores:

opciones_salir=frozenset(["no","NO"])

Retornar

96 - PostgreSQL : Base de datos desde


Python
Ver video
La tercer base de datos que veremos su acceso desde Python es PostgreSQL.

Se encuentra invitado para desarrollar un curso completo de PostgreSQL Ya!


Tenga en cuenta que debe tener instalado el motor de base de datos
PostgreSQL para poder seguir este concepto. En el tutorial de PostgreSQL
están todos los pasos para su instalación.

Creación de una base de datos y una tabla desde el


programa pgAdmin.
Ejecutemos el programa pgAdmin accediendo desde el menú de Windows:
Se abre el navegador con la aplicación:

Para crear una base de datos presionamos el botón derecho del mouse donde
dice "Databases" y seleccionamos la opción "Create"->"Database...":
Aparece un diálogo donde debemos ingresar el nombre de la base de datos a
crear, la llamaremos "bd1":

Ahora podemos seleccionar en la ventana de la izquierda la base de datos


"bd1" que acabamos de crear:
Para poder ejecutar comandos SQL debemos presionar el botón derecho del
mouse sobre el nombre de la base de datos "bd1" y seleccionar la opción
"Query Tool..":

Ahora crearemos la tabla articulos en la base de datos "bd1":


Paquete de Python necesario para conectarnos a
PostgreSQL.
Utilizaremos el programa 'pip' que vimos anteriormente para instalar el paquete
necesario para interconectar 'Python' y 'PostgreSQL'.
Desde la línea de comandos ejecutamos el programa pip con el siguiente
paquete a instalar:

pip install psycopg2

Luego de ejecutar el programa pip podemos ver que nos informa que la
instalación del paquete se efectuó correctamente:

Conexión con el servidor de PostgreSQL.


El primer programa que implementaremos nos conectaremos con el servidor de
PostgreSQL e insertaremos un par de filas en la tabla 'articulos' que creamos
desde el programa 'pgAdmin'.
Programa: ejercicio333.py

import psycopg2

conexion1 = psycopg2.connect(database="bd1", user


="postgres", password="heladera")
cursor1=conexion1.cursor()
sql="insert into articulos(descripcion, precio) v
alues (%s,%s)"
datos=("naranjas", 23.50)
cursor1.execute(sql, datos)
datos=("peras", 34)
cursor1.execute(sql, datos)
datos=("bananas", 25)
cursor1.execute(sql, datos)
conexion1.commit()
conexion1.close()
Ejecutemos este programa para que se efectúe la carga de las tres filas en la
tabla 'articulos' de la base de datos 'bd1'.
Por el momento si queremos controlar que se han cargado las tres filas en la
tabla 'articulos' podemos abrir el 'pgAdmin' que viene com PostgreSQL y ver el
contenido de la tabla:
Lo primero que hacemos es importar el módulo que nos permite conectarnos
con PostgreSQL:

import psycopg2

Del módulo importado llamamos a la función connect pasando la ubicación con


el nombre de la base de datos, nombre de usuario y la clave de dicho usuario:

conexion1 = psycopg2.connect(database="bd1", user="postgres", password="heladera


")

Si por ejemplo el servidor de PostgreSQL no se encuentra en ejecución el


programa se detendrá en esta línea informando un error.
Luego a partir del objeto 'conexion1' llamamos al método 'cursor':

cursor1=conexion1.cursor()

Definimos un string con el comando SQL insert disponiendo la máscara %s


donde queremos que se sustituya por un valor que le pasaremos al método
execute:

sql="insert into articulos(descripcion, precio) values (%s,%s)"


La variable datos es una tupla que contiene los datos que se utilizarán en la
sustitución %s:

datos=("naranjas", 23.50)

Finalmente llamamos al método 'execute' y le pasamos las dos variables que


acabamos de crear:

cursor1.execute(sql, datos)

Es fundamental llamar al final al método 'commit' para que queden firmes los
comandos SQL 'insert':

conexion1.commit()

Recuperar todas las filas de una tabla.


Implementaremos un programa que solicite ejecutar un 'select' en la tabla
'articulos' de la base de datos 'bd1' y nos retorne todas sus filas.
Programa: ejercicio334.py

import psycopg2

conexion1 = psycopg2.connect(database="bd1", user


="postgres", password="123456")
cursor1=conexion1.cursor()
cursor1.execute("select codigo, descripcion, prec
io from articulos")
for fila in cursor1:
print(fila)
conexion1.close()
Cuando ejecutamos el programa podemos ver que se recuperan todas las filas
de la tabla 'articulos':
Luego de conectarnos y crear un cursor procedemos a ejecutar el comando
'select', recorremos con un for el 'cursor1':

cursor1=conexion1.cursor()
cursor1.execute("select codigo, descripcion, precio from articulos")
for fila in cursor1:
print(fila)

Borrado y modificación de filas.


Las otras dos actividades fundamentales que podemos hacer con una tabla es
borrar filas y modificar datos.
Desarrollaremos un pequeño programa que borre el artículo cuyo código sea el
1 y modifique el precio del artículo cuyo código sea 3.
Programa: ejercicio335.py

import psycopg2

conexion1 = psycopg2.connect(database="bd1", user


="postgres", password="123456")
cursor1=conexion1.cursor()
cursor1.execute("delete from articulos where codi
go=1")
cursor1.execute("update articulos set precio=50 w
here codigo=3")
conexion1.commit()
cursor1.execute("select codigo, descripcion, prec
io from articulos")
for fila in cursor1:
print(fila)
conexion1.close()
Cuando ejecutamos el programa podemos ver que se eliminó el artículo cuyo
código es 1 y se modificó el precio del artículo con código 3:

Luego de crear el cursor podemos llamar al método 'execute' varias veces y


pasar distintos comando SQL:
cursor1=conexion1.cursor()
cursor1.execute("delete from articulos where codigo=1")
cursor1.execute("update articulos set precio=50 where codigo=3")

Siempre que pasemos un comando SQL: insert, delete o update debemos


llamar al método commit para que quede firme los cambios en la base de
datos:

conexion1.commit()

Ejecutamos finalmente un 'select' para comprobar los cambios efectuados en la


tabla 'articulos':

cursor1.execute("select codigo, descripcion, precio from articulos")


for fila in cursor1:
print(fila)

Retornar

97 - PostgreSQL : interfaz visual con


tkinter y acceso a la base de datos
Ver video
Es muy posible que necesitemos en algunas situaciones acceder a una base
de datos de PostgreSQL desde una aplicación con una interfaz visual.

Problema:
Desarrollar una aplicación visual con la librería tkinter que permita implementar
los algoritmos de carga de artículos, consulta por código y listado completo.
Seguiremos trabajando con la tabla 'articulos' que creamos en el concepto
anterior.
Las interfaz visual para la carga debe ser:
Las interfaz visual para la consulta:

Y finalmente la interfaz para el listado completo:


Para trabajar un poco más ordenado en la resolución de este problema lo
dividiremos en dos módulos 'formularioarticulos.py' y 'articulos.py'.
El primer paso será crear una carpeta llamada 'proyecto5' y dentro de esta
crearemos los dos módulos:

El módulo 'formularioarticulos.py' contiene toda la lógica de presentación de


datos y hace uso del otro módulo para el acceso a la base de datos
PostgreSQL.
módulo: formularioarticulos.py

import tkinter as tk
from tkinter import ttk
from tkinter import messagebox as mb
from tkinter import scrolledtext as st
import articulos

class FormularioArticulos:
def __init__(self):
self.articulo1=articulos.Articulos()
self.ventana1=tk.Tk()
self.ventana1.title("Mantenimiento de art
ículos")
self.cuaderno1 = ttk.Notebook(self.ventan
a1)
self.carga_articulos()
self.consulta_por_codigo()
self.listado_completo()
self.cuaderno1.grid(column=0, row=0, padx
=10, pady=10)
self.ventana1.mainloop()

def carga_articulos(self):
self.pagina1 = ttk.Frame(self.cuaderno1)
self.cuaderno1.add(self.pagina1, text="Ca
rga de artículos")
self.labelframe1=ttk.LabelFrame(self.pagi
na1, text="Artículo")
self.labelframe1.grid(column=0, row=0, pa
dx=5, pady=10)
self.label1=ttk.Label(self.labelframe1, t
ext="Descripción:")
self.label1.grid(column=0, row=0, padx=4,
pady=4)
self.descripcioncarga=tk.StringVar()
self.entrydescripcion=ttk.Entry(self.labe
lframe1, textvariable=self.descripcioncarga)
self.entrydescripcion.grid(column=1, row=
0, padx=4, pady=4)
self.label2=ttk.Label(self.labelframe1, t
ext="Precio:")
self.label2.grid(column=0, row=1, padx=4,
pady=4)
self.preciocarga=tk.StringVar()
self.entryprecio=ttk.Entry(self.labelfram
e1, textvariable=self.preciocarga)
self.entryprecio.grid(column=1, row=1, pa
dx=4, pady=4)
self.boton1=ttk.Button(self.labelframe1,
text="Confirmar", command=self.agregar)
self.boton1.grid(column=1, row=2, padx=4,
pady=4)

def agregar(self):
datos=(self.descripcioncarga.get(), self.
preciocarga.get())
self.articulo1.alta(datos)
mb.showinfo("Información", "Los datos fue
ron cargados")
self.descripcioncarga.set("")
self.preciocarga.set("")

def consulta_por_codigo(self):
self.pagina2 = ttk.Frame(self.cuaderno1)
self.cuaderno1.add(self.pagina2, text="Co
nsulta por código")
self.labelframe1=ttk.LabelFrame(self.pagi
na2, text="Artículo")
self.labelframe1.grid(column=0, row=0, pa
dx=5, pady=10)
self.label1=ttk.Label(self.labelframe1, t
ext="Código:")
self.label1.grid(column=0, row=0, padx=4,
pady=4)
self.codigo=tk.StringVar()
self.entrycodigo=ttk.Entry(self.labelfram
e1, textvariable=self.codigo)
self.entrycodigo.grid(column=1, row=0, pa
dx=4, pady=4)
self.label2=ttk.Label(self.labelframe1, t
ext="Descripción:")
self.label2.grid(column=0, row=1, padx=4,
pady=4)
self.descripcion=tk.StringVar()
self.entrydescripcion=ttk.Entry(self.labe
lframe1, textvariable=self.descripcion, state="re
adonly")
self.entrydescripcion.grid(column=1, row=
1, padx=4, pady=4)
self.label3=ttk.Label(self.labelframe1, t
ext="Precio:")
self.label3.grid(column=0, row=2, padx=4,
pady=4)
self.precio=tk.StringVar()
self.entryprecio=ttk.Entry(self.labelfram
e1, textvariable=self.precio, state="readonly")
self.entryprecio.grid(column=1, row=2, pa
dx=4, pady=4)
self.boton1=ttk.Button(self.labelframe1,
text="Consultar", command=self.consultar)
self.boton1.grid(column=1, row=3, padx=4,
pady=4)

def consultar(self):
datos=(self.codigo.get(), )
respuesta=self.articulo1.consulta(datos)
if len(respuesta)>0:
self.descripcion.set(respuesta[0][0])
self.precio.set(respuesta[0][1])
else:
self.descripcion.set('')
self.precio.set('')
mb.showinfo("Información", "No existe
un artículo con dicho código")

def listado_completo(self):
self.pagina3 = ttk.Frame(self.cuaderno1)
self.cuaderno1.add(self.pagina3, text="Li
stado completo")
self.labelframe1=ttk.LabelFrame(self.pagi
na3, text="Artículo")
self.labelframe1.grid(column=0, row=0, pa
dx=5, pady=10)
self.boton1=ttk.Button(self.labelframe1,
text="Listado completo", command=self.listar)
self.boton1.grid(column=0, row=0, padx=4,
pady=4)
self.scrolledtext1=st.ScrolledText(self.l
abelframe1, width=30, height=10)
self.scrolledtext1.grid(column=0,row=1, p
adx=10, pady=10)

def listar(self):
respuesta=self.articulo1.recuperar_todos(
)
self.scrolledtext1.delete("1.0", tk.END)
for fila in respuesta:
self.scrolledtext1.insert(tk.END, "có
digo:"+str(fila[0])+"\ndescripción:"+fila[1]+"\np
recio:"+str(fila[2])+"\n\n")

aplicacion1=FormularioArticulos()
El módulo 'articulos.py' contiene toda la lógica de acceso a datos.
módulo: articulos.py

import psycopg2

class Articulos:

def abrir(self):
conexion = psycopg2.connect(database="bd1
", user="postgres", password="123456")
return conexion

def alta(self, datos):


cone=self.abrir()
cursor=cone.cursor()
sql="insert into articulos(descripcion, p
recio) values (%s,%s)"
cursor.execute(sql, datos)
cone.commit()

def consulta(self, datos):


cone=self.abrir()
cursor=cone.cursor()
sql="select descripcion, precio from arti
culos where codigo=%s"
cursor.execute(sql, datos)
return cursor.fetchall()

def recuperar_todos(self):
cone=self.abrir()
cursor=cone.cursor()
sql="select codigo, descripcion, precio f
rom articulos"
cursor.execute(sql)
return cursor.fetchall()
Tener en cuenta que el módulo principal se encuentra en el archivo
'formularioarticulos.py' y es el que debemos ejecutar:

Cuando al programa lo ejecutemos desde la línea de comandos fuera del editor


VS Code debemos recordar de llamar al módulo principal:
Analicemos un poco el código del módulo 'formularioarticulos.py', lo primero
que hacemos es importar los módulos necesarios para implementar la interfaz
visual:

import tkinter as tk
from tkinter import ttk
from tkinter import messagebox as mb
from tkinter import scrolledtext as st

Otro import fundamental es el módulo 'articulos.py' donde tenemos


implementada la clase 'Articulos' que es la que se comunica con el gestor de
base de datos PostgreSQL:

import articulos

La clase visual la hemos llamado 'FormularioArticulos' y en el método __init__


creamos un objeto de la clase 'Articulos' que se encuentra en el otro módulo:

class FormularioArticulos:
def __init__(self):
self.articulo1=articulos.Articulos()
También en el método __init__ llamamos a una serie de métodos para crear
cada una de las páginas del objeto de la clase 'Notebook':

self.ventana1=tk.Tk()
self.ventana1.title("Mantenimiento de artículos")
self.cuaderno1 = ttk.Notebook(self.ventana1)
self.carga_articulos()
self.consulta_por_codigo()
self.listado_completo()
self.cuaderno1.grid(column=0, row=0, padx=10, pady=10)
self.ventana1.mainloop()

Cuando desde la pestaña "Carga de artículos" se presiona el botón "Confirmar"


lo primero que hacemos es crear una tupla con los dos datos ingresados en los
controles "Entry":

def agregar(self):
datos=(self.descripcioncarga.get(), self.preciocarga.get())

Luego llamamos al método alta del objeto 'articulo1' y le pasamos la tupla con
los datos a añadir:

self.articulo1.alta(datos)
mb.showinfo("Información", "Los datos fueron cargados")
self.descripcion.set("")
self.precio.set("")

En este momento nos conviene analizar el método 'alta' de la clase 'Articulos'


que se encuentra en el otro módulo:

def alta(self, datos):


cone=self.abrir()
cursor=cone.cursor()
sql="insert into articulos(descripcion, precio) values (%s,%s)"
cursor.execute(sql, datos)
cone.commit()

En el método 'alta' abrimos la conexión con el PostgreSQL, creamos un cursor


y llamamos seguidamente al método execute pasando un string con el
comando SQL 'insert' y los datos a almacenar. Llamamos al método commit de
la conexión.
Consulta por código
Cuando se presiona el botón "Consultar" se ejecuta el método siguiente:

def consultar(self):
datos=(self.codigo.get(), )
respuesta=self.articulo1.consulta(datos)
if len(respuesta)>0:
self.descripcion.set(respuesta[0][0])
self.precio.set(respuesta[0][1])
else:
self.descripcion.set('')
self.precio.set('')
mb.showinfo("Información", "No existe un artículo con dicho código")

Creamos una tubla con un solo dato (es obligatoria la coma para que Python lo
considere una tupla:

datos=(self.codigo.get(), )

Llamamos al método consulta de la clase 'Articulos' que se encuentra en el otro


módulo. El método 'consulta' retorna una lista vacía si no existe el código de
artículo ingresado o una lista con una tupla en su interior.
El método 'consulta' de la clase 'Articulos' llama al método 'fetchall' del cursor
respectivo:

def consulta(self, datos):


cone=self.abrir()
cursor=cone.cursor()
sql="select descripcion, precio from articulos where codigo=%s"
cursor.execute(sql, datos)
return cursor.fetchall()

Listado completo
Para mostrar todas las filas de la tabla 'articulos' hemos dispuesto un objeto de
la clase 'scrolledtext':
def listar(self):
respuesta=self.articulo1.recuperar_todos()
self.scrolledtext1.delete("1.0", tk.END)
for fila in respuesta:
self.scrolledtext1.insert(tk.END, "código:"+str(fila[0])+
"\ndescripción:"+fila[1]+
"\nprecio:"+str(fila[2])+"\n\n")

Llamamos al método 'recuperar_todos' de la clase 'Articulos' y obtenemos una


lista con un conjunto de tuplas con cada fila de la tabla.
El algoritmo 'recuperar_todos' de la clase Articulos es:

def recuperar_todos(self):
cone=self.abrir()
cursor=cone.cursor()
sql="select codigo, descripcion, precio from articulos"
cursor.execute(sql)
return cursor.fetchall()

Problema propuesto
• Agregar dos pestañas al programa de administración de artículos que
permitan borrar un artículo ingresando su código y otra opción que
permita consultar y modificar la descripción y precio de un artículo.
La interfaces visuales a implementar son:
Ver video
Solución

Retornar

98 - Módulos y paquetes en Python


Vimos en conceptos anteriores que podemos dividir una aplicación en varios
módulos y luego importarlos.
Recordemos que un módulo es un archivo con extensión 'py' y contiene en su
interior funciones, clases, definición de variables etc.
Veremos ahora que un paquete en Python agrupa un conjunto de módulos
relacionados y se los localiza en un directorio.
Veremos con un sencillo problema como creamos un paquete en Python.

Problema:
Ver video
Desarrollar una aplicación visual que muestre dos botones. Al presionar el
primero mostrar otra ventana para el login, y al presionar el segundo mostrar
una ventana de mensajes.
Crear un paquete llamado 'formularios' que contenga en su interior dos
módulos llamados 'login.py' y 'mensaje.py'.
La aplicación principal llamarla 'principal.py'
Debemos crear una carpeta llamada 'formularios' y en su interior tres archivos:
'login.py', 'mensaje.py' y '__init__.py'.
El archivo '__init__.py' generalmente se encuentra vacío y tiene por objetivo
indicar al intérprete de Python que dicha carpeta es un paquete.
Es decir que debemos tener los siguientes archivos y carpeta en nuestra
aplicación:

módulo: login.py

import tkinter as tk
from tkinter import ttk

class Aplicacion:
def __init__(self):
self.ventana1=tk.Tk()
self.labelframe1=ttk.LabelFrame(self.vent
ana1, text="Login:")
self.labelframe1.grid(column=0, row=0, pa
dx=5, pady=10)
self.login()

def login(self):
self.label1=ttk.Label(self.labelframe1, t
ext="Nombre de usuario:")
self.label1.grid(column=0, row=0, padx=4,
pady=4)
self.entry1=ttk.Entry(self.labelframe1)
self.entry1.grid(column=1, row=0, padx=4,
pady=4)
self.label2=ttk.Label(self.labelframe1, t
ext="Ingrese clave:")
self.label2.grid(column=0, row=1, padx=4,
pady=4)
self.entry2=ttk.Entry(self.labelframe1, s
how="*")
self.entry2.grid(column=1, row=1, padx=4,
pady=4)
self.boton1=ttk.Button(self.labelframe1,
text="Ingresar",command=self.ingresar)
self.boton1.grid(column=1, row=2, padx=4,
pady=4)

def ingresar(self):
self.ventana1.destroy()
def mostrar():
aplicacion1=Aplicacion()
módulo: mensaje.py

from tkinter import messagebox as mb

def mostrar(mensaje):
mb.showerror("Cuidado",mensaje)
Recordar de crear el archivo '__init__.py' en la carpeta 'formularios' y sin
contenido (luego veremos que podemos disponer código en su interior que se
ejecutará cuando importemos algún módulo del paquete)
Por otro lado creamos en la carpeta superior el script que contendrá la
aplicación principal de nuestro programa que lo llamaremos 'principal.py'
principal.py

import tkinter as tk
from tkinter import ttk

import formularios.login
import formularios.mensaje

class Aplicacion:
def __init__(self):
self.ventana1=tk.Tk()
self.ventana1.title("Hola Mundo")
self.boton1=ttk.Button(self.ventana1, tex
t="Mostrar Mensaje", command=self.mostrar_mensaje
)
self.boton1.grid(column=0, row=0)
self.boton2=ttk.Button(self.ventana1, tex
t="Mostrar formulario de login", command=self.mos
trar_login)
self.boton2.grid(column=0, row=1)
self.ventana1.mainloop()

def mostrar_mensaje(self):
formularios.mensaje.mostrar("Es una prueb
a de acceder a módulos de un paquete")

def mostrar_login(self):
formularios.login.mostrar()

aplicacion1=Aplicacion()
Si ejecutamos la aplicación desde el script 'principal.py' tenemos como
resultado en pantalla al presionar el botón "Mostrar formulario de login":

Como vemos la sintaxis para importar un módulo contenido en un paquete


debemos anteceder al nombre del módulo el nombre del paquete:
import formularios.login
import formularios.mensaje

Luego podemos acceder al módulo respectivo indicando primero el nombre del


paquete, seguidamente el nombre del módulo y finalmente el nombre de la
función:

formularios.login.mostrar()

De forma similar llamamos a la función 'mostrar' del módulo 'mensaje'


contenido en el paquete 'formularios':

formularios.mensaje.mostrar("Es una prueba de acceder a módulos de un pa


quete")

Acotaciones.
1. Recordemos que podemos crear un alias cuando importamos un módulo
con el fin de escribir menos cada vez que lo accedemos:

2. import tkinter as tk
3. from tkinter import ttk
4.
5. import formularios.login as formlogin
6. import formularios.mensaje as formmensaje
7.
8. class Aplicacion:
9. def __init__(self):
10. self.ventana1=tk.Tk()
11. self.ventana1.title("Hola Mundo")
12. self.boton1=ttk.Button(self.ventana1, text="Mostrar Mensaje", com
mand=self.mostrar_mensaje)
13. self.boton1.grid(column=0, row=0)
14. self.boton2=ttk.Button(self.ventana1, text="Mostrar formulario de
login", command=self.mostrar_login)
15. self.boton2.grid(column=0, row=1)
16. self.ventana1.mainloop()
17.
18. def mostrar_mensaje(self):
19. formmensaje.mostrar("Es una prueba de acceder a módulos de un paq
uete")
20.
21. def mostrar_login(self):
22. formlogin.mostrar()
23.
24. aplicacion1=Aplicacion()

Como vemos llamamos a la función mostrar del módulo 'login'


directamente antecediendo el nombre del alias creado:

formlogin.mostrar()

25. También podemos hacer uso de la sintaxis del 'from' para importar
módulos de un determinado paquete:

26. import tkinter as tk


27. from tkinter import ttk
28.
29. from formularios import login
30. from formularios import mensaje
31.
32. class Aplicacion:
33. def __init__(self):
34. self.ventana1=tk.Tk()
35. self.ventana1.title("Hola Mundo")
36. self.boton1=ttk.Button(self.ventana1, text="Mostrar Mensaje", com
mand=self.mostrar_mensaje)
37. self.boton1.grid(column=0, row=0)
38. self.boton2=ttk.Button(self.ventana1, text="Mostrar formulario de
login", command=self.mostrar_login)
39. self.boton2.grid(column=0, row=1)
40. self.ventana1.mainloop()
41.
42. def mostrar_mensaje(self):
43. mensaje.mostrar("Es una prueba de acceder a módulos de un paquete
")
44.
45. def mostrar_login(self):
46. login.mostrar()
47.
48. aplicacion1=Aplicacion()

49. Un paquete en Python tiene en su interior módulos, pero puede tener


otros subpaquetes que se deben crear en forma similar al paquete
padre. También el subpaquete además de los módulos debe tener el
archivo '__init__.py'.
Cuando importamos un subpaquete debemos indicar el nombre de la
carpeta del paquete principal, luego el nombre de la carpeta del
subpaquete y finalmente el nombre del módulo:

import formularios.modales.login
import formularios.modales.mensaje
import formularios.nomodales.ayuda

El nivel de subcarpetas dependerá de la complejidad de la aplicación


que estemos implementando.

Retornar

99 - Acceso a Internet mediante el


paquete urllib
Ver video
Para acceder a recursos de Internet Python nos proporciona en la Biblioteca
estándar un paquete fundamental llamado urllib.
Si bien lo más común es que accedamos a las páginas web a través de un
navegador web (Chrome, Firefox, Edge etc.) podemos también hacerlo
mediante un programa codificado en Python.
El primer módulo que veremos del paquete 'urllib' se llama 'request' y tiene por
objetivo permitir acceder a cualquier recurso alojado en Internet.
El primer ejemplo nos mostrará la facilidad que tenemos en Python para
recuperar un archivo html localizado en Internet.
Lectura de una página HTML.
Recuperar la página html 'pagina1.html' que se encuentra localizada en:

http://www.scratchya.com.ar/pythonya/ejercicio336/pagina1.html

Programa: ejercicio336.py

from urllib import request

pagina=request.urlopen("http://www.scratchya.com.
ar/pythonya/ejercicio336/pagina1.html")
datos=pagina.read()
print(datos)
La ejecución del script nos muestra el contenido del archivo 'pagina1.html' que
se encuentra en el servidor antes mencionado:

Un navegador web además de recuperar el contenido del archivo HTML como


hemos hecho en Python, procede a interpretarlo y mostrarlo con el formato
adecuado:
Lo primero que hacemos es importar el módulo 'request' que se encuentra en
el paquete 'urllib':

from urllib import request

Mediante la función 'urlopen' recuperamos del servidor el recurso que le


indicamos como parámetro:

pagina=request.urlopen("http://www.scratchya.com.ar/pythonya/ejercicio336/pagina
1.html")

La función 'urlopen' retorna la referencia de un objeto de la clase


'HTTPResponse' y se almacena en la variable 'pagina'.
Procedemos seguidamente a llamar al método 'read' que tiene por objetivo
recuperar todos el contenido de la página HTML:

datos=pagina.read()
print(datos)

Transformar a formato 'utf-8'


El método 'read' recupera los datos como un bloque de bytes, si vemos la
imagen anterior donde imprimimos la variable 'datos' podemos comprobar que
aparece entre comillas y antecedido por el caracter 'b':
b'<!DOCTYPE html>\r\n<html lang="es"> ........

Luego si queremos convertir el bloque de bytes a 'utf-8' debemos hacerlo


llamando al método 'decode' indicando el formato respectivo:
Programa: ejercicio336.py

from urllib import request

pagina=request.urlopen("http://www.scratchya.com.
ar/pythonya/ejercicio336/pagina1.html")
datos=pagina.read()
datosutf8=datos.decode("utf-8")
print(datosutf8)
Si ejecutamos ahora nuevamente la aplicación podemos ver el contenido
convertido a texto con formato 'utf-8' (formato de codificación de caracteres
más común empleado en Internet para representar múltiples idiomas):
Lectura de una página HTML u otro recurso y posterior
grabación del archivo en forma local.
Recuperar la página html 'pagina1.html' y el archivo 'imagen1.jpg' que se
encuentran localizados en:

http://www.scratchya.com.ar/pythonya/ejercicio336/pagina1.html
http://www.scratchya.com.ar/pythonya/ejercicio336/imagen1.jpg

luego grabar los dos archivos en forma local en el equipo donde se está
ejecutando el script de Python.
Programa: ejercicio337.py

from urllib import request


pagina=request.urlopen("http://www.scratchya.com.
ar/pythonya/ejercicio336/pagina1.html")
datos=pagina.read()
archivo1=open("pagina1.html","wb")
archivo1.write(datos)
archivo1.close()

imagen=request.urlopen("http://www.scratchya.com.
ar/pythonya/ejercicio336/imagen1.jpg")
datos=imagen.read()
archivo2=open("imagen1.jpg","wb")
archivo2.write(datos)
archivo2.close()
Procedemos primero a importar el módulo 'request' del paquete 'ulrlib':

from urllib import request

Recuperamos del servidor el recurso 'pagina1.html' en formato binario:

pagina=request.urlopen("http://www.scratchya.com.ar/pythonya/ejercicio336/pagina
1.html")
datos=pagina.read()

Creamos un archivo binario en nuestro equipo con el nombre 'pagina1.html' y


procedemos a almacenar el bloque de bytes recuperados del servidor:

archivo1=open("pagina1.html","wb")
archivo1.write(datos)

Cerramos el archivo que acabamos de crear llamando al método 'close':

archivo1.close()

Los mismos pasos damos para recuperar el archivo 'imagen1.jpg' y crear el


archivo en nuestro equipo:
pagina=request.urlopen("http://www.scratchya.com.ar/pythonya/ejercicio336/pagina
1.html")
datos=pagina.read()
archivo1=open("pagina1.html","wb")
archivo1.write(datos)
archivo1.close()

Es decir no es importante el formato del archivo (html/jgp/gif/json etc.) para


recuperarlo de un servidor de Internet.

Módulo 'error' del paquete 'urllib'.


Si el recurso no se encuentra en el servidor de internet o se genera cualquier
otro tipo de error, podemos capturar la excepción 'HTTPError' del paquete
'urllib'
Confeccionaremos un script que intente recuperar una página HTML que no se
encuentre en el servidor:

http://www.scratchya.com.ar/pythonya/ejercicio336/paginax.html

luego capturaremos la excepción 'HTTPError'


Programa: ejercicio338.py

from urllib import request


from urllib import error

try:
pagina=request.urlopen("http://www.scratchya.
com.ar/pythonya/ejercicio336/paginax.html")
datos=pagina.read().decode("utf-8")
print(datos)
except error.HTTPError as err:
print(f"Código de respuesta HTTP devuelto por
el servidor {err.code}")
print(f"No existe el recurso {err.filename}")
Lo primero que hacemos además de importar el módulo 'request', es importar
el módulo 'error' también almacenado en el paquete 'urllib':

from urllib import request


from urllib import error

Al método 'urlopen' lo debemos disponer dentro de un bloque try:

try:
pagina=request.urlopen("http://www.scratchya.com.ar/pythonya/ejercicio336/pa
ginax.html")
datos=pagina.read().decode("utf-8")
print(datos)

El método 'urlopen' puede generar una excepción de tipo 'HTTPError':

except error.HTTPError as err:


print(f"Código de respuesta HTTP devuelto por el servidor {err.code}")
print(f"No existe el recurso {err.filename}")

Mostramos en el bloque except datos almacenados en la excepción elevada


por el método 'urlopen':

Como el archivo 'paignax.html' no existe luego se ejecuta el bloque except


donde podemos consultar los datos almacenados en la excepción.
Problema propuesto
• Confeccionar una aplicación visual con tkinter que permita ingresar en
un control de tipo 'Entry' la URL de un sitio web y al presionar un botón
recuperar los datos y mostrarlos en un control de tipo 'ScrolledText':

Ver video
Solución

Retornar

100 - Procesar archivos con formato


JSON en Python (módulo json)
Vimos en el concepto anterior como podemos acceder a recursos de Internet
desde Python. Un recurso muy común para transferir datos en Internet son los
archivos con formato JSON.
La Biblioteca estándar de Python cuenta con un módulo que nos facilita
trabajar con archivos JSON.
Ver video
El formato JSON se lo puede transformar en Python a un diccionario. Por
ejemplo:

import json

cadena="""
{
"codigo":"1",
"descripcion":"papas",
"precio":"13.45"
}
"""
print(cadena) # imprimimos un string
diccionario=json.loads(cadena)
print(diccionario) # imprimimos un diccionario
De forma similar si disponemos de un vector, luego la transformación será a
una lista con elementos de tipo diccionario:

import json

cadena="""
[
{
"codigo":"1",
"descripcion":"papas",
"precio":"13.45"
},
{
"codigo":"2",
"descripcion":"manzanas",
"precio":"45"
}
]
"""
print(cadena) # imprimimos un string
lista=json.loads(cadena)
print(lista) # imprimimos una lista

Problema 1
Implementar un sitio WEB en PHP que retorne un archivo con formato JSON
con los datos de diferentes artículos.
Para resolver el problema debemos tener un conocimiento del lenguaje PHP y
del gestor de base de datos MySQL.
Cree una base de datos llamada 'pythonya' y una tabla 'articulos' con los
siguientes datos:

CREATE TABLE `articulos` (


`codigo` int(11) NOT NULL AUTO_INCREMENT,
`descripcion` varchar(50) DEFAULT NULL,
`precio` float DEFAULT NULL,
PRIMARY KEY (`codigo`)
);

insert into `articulos` values (1,'papas',15);


insert into `articulos` values (2,'manzanas',24);
insert into `articulos` values (3,'peras',45.3);
insert into `articulos` values (4,'naranjas',22);
insert into `articulos` values (5,'pomelos',29);
insert into `articulos` values (6,'frutillas',130);
insert into `articulos` values (7,'anana',75);

Seguidamente proceda a codificar el siguiente archivo PHP que se conecta a la


base de datos 'pythonya', recupera todas las filas de la tabla 'articulos' y
finalmente retorna todos los datos en formato JSON:
Programa: retornararticulos.php

<?php
header('Content-Type: application/json');

$server="localhost";
$usuario="root";
$clave="";
$base="pythonya";
$conexion=mysqli_connect($server,$usuario,$clave,
$base) or die("problemas") ;
mysqli_set_charset($conexion,'utf8');

$datos = mysqli_query($conexion, "SELECT codigo,


descripcion, precio from articulos");
$resultado = mysqli_fetch_all($datos, MYSQLI_ASSO
C);
echo json_encode($resultado);
?>
Si ya ha estudiado un poco de PHP sabe que al solicitar ésta página desde un
navegador web lo que sucede es que retorna un archivo en formato JSON:
Ahora implementaremos una aplicación en Python que recupere y muestre los
datos del archivo JSON generado en un servidor de Internet accediendo a una
base de datos MySQL a través de PHP:
Programa: ejercicio340.py

from urllib import request


import json

pagina=request.urlopen("http://localhost/pythonya
/retornararticulos.php")
datos=pagina.read().decode("utf-8")
print(datos) # imprimimos un string
print("_"*100)
lista=json.loads(datos) # convertimos el string a
una lista
print(lista) # imprimimos una lista
print("_"*100)
for elemento in lista:
print(f"{elemento['codigo']} {elemento['desc
ripcion']:50} {elemento['precio']:>12}")
El resultado de ejecutar la aplicación (recuerde tener activo el servidor web con
PHP y MySQL):
Importamos los módulos request y json:

from urllib import request


import json

Solicitamos al servidor local (localhost) el recurso 'retornararticulos.php'


localizado en la carpeta 'pythonya':

pagina=request.urlopen("http://localhost/pythonya/retornararticulos.php")

Leemos y decodificamos a formato 'utf-8':

datos=pagina.read().decode("utf-8")

La variable 'datos' es un string:

print(datos) # imprimimos un string

Mediante el método 'loads' del módulo 'json' transformamos el contenido del


string en una lista con elementos de tipo diccionario:

lista=json.loads(datos) # convertimos el string a una lista

Imprimimos la lista completa:

print(lista) # imprimimos una lista

Hacemos una impresión de cada elemento de la lista con un formato más


legible para el usuario:

for elemento in lista:


print(f"{elemento['codigo']} {elemento['descripcion']:50} {elemento['preci
o']:>12}")

Problema 2
Ingresar por teclado el código de un artículo, seguidamente recuperar los datos
de dicho artículo del servidor local. Pasar el código del artículo como parámetro
'GET' en la llamada.
La aplicación en PHP que recupera los datos de un determinado artículo que
llega como parámetro es:
Programa: retornararunarticulo.php
Ver video

<?php
header('Content-Type: application/json');

$server="localhost";
$usuario="root";
$clave="";
$base="pythonya";
$conexion=mysqli_connect($server,$usuario,$clave,
$base) or die("problemas") ;
mysqli_set_charset($conexion,'utf8');

$datos = mysqli_query($conexion, "SELECT codigo,


descripcion, precio from articulos where codigo=$
_GET[codigo]");
$resultado = mysqli_fetch_all($datos, MYSQLI_ASSO
C);
echo json_encode($resultado);
?>
Es importante notar que ahora recuperamos solo una fila de la tabla 'articulos',
es decir aquel que coincide con el código de artículo pasado en la llamada:

$datos = mysqli_query($conexion, "SELECT codigo, descripcion, precio from articu


los where codigo=$_GET[codigo]");

Ahora veamos el programa Python que llama a la página PHP anterior.


Programa: ejercicio341.py

from urllib import request


import json
codigo=input("Ingrese el código de artículo a con
sultar:")
pagina=request.urlopen(f"http://localhost/pythony
a/retornarunarticulo.php?codigo={codigo}")
datos=pagina.read().decode("utf-8")
lista=json.loads(datos)
if len(lista)>0:
print(f"Descripción:{lista[0]['descripcion']}
")
print(f"Precio:{lista[0]['precio']}")
else:
print("No existe un artículo con el código in
gresado")
El resultado de ejecutar la aplicación y cargar un código de artículo a consultar
(recuerde tener activo el servidor web con PHP y MySQL):

Cuando nos conectamos al servidor le pasamos un parámetro llamado código


y un número que ingresamos previamente por teclado:
codigo=input("Ingrese el código de artículo a consultar:")
pagina=request.urlopen(f"http://localhost/pythonya/retornarunarticulo.php?codigo
={codigo}")

Una vez que recuperamos los datos del servidor procedemos a convertir el
string devuelto:

lista=json.loads(datos)

Si la lista no está vacía procedemos a mostrar la descripción y precio del


artículo consultado:

if len(lista)>0:
print(f"Descripción:{lista[0]['descripcion']}")
print(f"Precio:{lista[0]['precio']}")

En caso contrario significa que intentamos consultar un código de artículo


inexistente:

else:
print("No existe un artículo con el código ingresado")

Problemas propuestos
• Confeccionar una aplicación visual con tkinter que permita mostrar todos
los artículos. Recuperar del servidor web llamando al recurso
'retornararticulos.php'.
Disponer dos botones para poder navegar entre los distintos registros
recuperados.
La interfaz visual debe ser similar a:
Ver video
• El sitio web

• https://jsonplaceholder.typicode.com/

se puede utilizar para recuperar datos con diferentes formatos (JSON


por ejemplo) y probar nuestros algoritmos.
Confeccionar una aplicación en Python que recupere el archivo JSON de
la siguiente dirección web:

https://jsonplaceholder.typicode.com/posts

Nos retorna un archivo JSON con un formato similar a:

[
{
"userId": 1,
"id": 1,
"title": "sunt aut facere repellat provident occaecati excepturi opti
o reprehenderit",
"body": "quia et suscipit\nsuscipit recusandae consequuntur expedita
et cum\nreprehenderit
molestiae ut ut quas totam\nnostrum rerum est autem sunt rem
eveniet architecto"
},
{
"userId": 1,
"id": 2,
"title": "qui est esse",
"body": "est rerum tempore vitae\nsequi sint nihil reprehenderit dolo
r beatae ea dolores
neque\nfugiat blanditiis voluptate porro vel nihil molestiae
ut reiciendis\nqui
aperiam non debitis possimus qui neque nisi nulla"
}]

Convertir los datos recuperados a una lista y mediante un for mostrar los
atributos "userID", "id", "title" y "body".
Ver video
• Hacer la misma actividad que el problema anterior con el recurso que
devuelve la dirección:

• https://jsonplaceholder.typicode.com/users

Nos retorna un archivo JSON con un formato similar a:

[
{
"id": 1,
"name": "Leanne Graham",
"username": "Bret",
"email": "[email protected]",
"address": {
"street": "Kulas Light",
"suite": "Apt. 556",
"city": "Gwenborough",
"zipcode": "92998-3874",
"geo": {
"lat": "-37.3159",
"lng": "81.1496"
}
},
"phone": "1-770-736-8031 x56442",
"website": "hildegard.org",
"company": {
"name": "Romaguera-Crona",
"catchPhrase": "Multi-layered client-server neural-net",
"bs": "harness real-time e-markets"
}
},
{
"id": 2,
"name": "Ervin Howell",
"username": "Antonette",
"email": "[email protected]",
"address": {
"street": "Victor Plains",
"suite": "Suite 879",
"city": "Wisokyburgh",
"zipcode": "90566-7771",
"geo": {
"lat": "-43.9509",
"lng": "-34.4618"
}
},
"phone": "010-692-6593 x09125",
"website": "anastasia.net",
"company": {
"name": "Deckow-Crist",
"catchPhrase": "Proactive didactic contingency",
"bs": "synergize scalable supply-chains"
}
}
]

Convertir los datos recuperados a una lista y mediante un for mostrar


todos los atributos.
Ver video
Solución

Retornar

101 - Serialización y deserialización


en Python (módulo json)
En el concepto anterior trabajamos con la deserialización de recursos JSON
localizados en un servidor y su posterior transformación a listas con elementos
de tipo diccionario.

Definiciones básicas.
• Serialización: Consiste en convertir un objeto de Python (normalmente
una lista o diccionario) en un string.

• Deserialización: Consiste en convertir un string en un objeto de Python


(normalmente una lista o diccionario).

Como vemos son los dos caminos posibles para transformar una estructura de
datos en otra estructura.

Problema 1
Definir un string en Python con la estructura interna de un archivo JSON.
Deserializar el string y convertirlo a una lista de Python. Luego volver a
serializar la lista a un string.
Programa: ejercicio345.py
Ver video

import json

cadena1="""
[
{
"codigo":"1",
"descripcion":"papas",
"precio":"12"
},
{
"codigo":"2",
"descripcion":"naranjas",
"precio":"25"
}
]
"""
print(type(cadena1))
print(cadena1)
print("_"*80)
lista=json.loads(cadena1)
print(type(lista))
print(lista)
print("_"*80)
cadena2=json.dumps(lista)
print(type(cadena2))
print(cadena2)
El resultado de ejecutar el siguente script en Python es:
Definimos e inicializamos una variable string:

cadena1="""
[
{
"codigo":"1",
"descripcion":"papas",
"precio":"12"
},
{
"codigo":"2",
"descripcion":"naranjas",
"precio":"25"
}
]
"""

Mediante la función 'type' podemos confirmar que la variable 'cadena1' es de


tipo 'str':

print(type(cadena1))

Ahora mediante la función 'loads' del módulo 'json' que vimos en el concepto
anterior deserializamos el string:

lista=json.loads(cadena1)

Si imprimimos el tipo de la variable 'lista' podemos verificar que se trata de tipo


'list':

print(type(lista))

Podemos ahora procesar la lista 'lista1', en nuestro caso solo la imprimimos en


forma completa:

print(lista)

Para convertir una lista a tipo string debemos utilizar la función 'dumps' del
módulo 'json':

cadena2=json.dumps(lista)

Podemos comprobar que la variable 'cadena2' es de tipo string mediante la


función 'type':

print(type(cadena2))
print(cadena2)

Transformación de datos entre Python y JSON


Los tipos de datos en JSON son muy similares a los tipos de datos en Python,
pero no son exactamente iguales.
La conversión en los procesos de serializar y deserializar son:

Python JSON

dic object

list o tupla array

str string

int y float number

True true

False false

None null

Retornar

También podría gustarte