Está en la página 1de 59

PROGRAMACIÓN I

UNIDAD I: INTRODUCCIÓN A LA PROGRAMACIÓN DE COMPUTADORAS


En un sentido general, programar es planificar y ordenar las acciones necesarias para realizar un proyecto.
Programar es una actividad (para algunos un arte) mediante la cual indicamos la secuencia de acciones que debe
realizar una máquina para cumplir con algún objetivo determinado.
Aunque parezca que programar una computadora es simplemente escribir las instrucciones que queremos que esta
cumpla, la resolución de problemas mediante la creación de programas informáticos (software) suele ser un proceso
arduo.
Comienza siempre con una necesidad o problema a resolver y, al contrario de lo que se cree, no finaliza con la obtención
de un programa ejecutable, sino que el mismo estará sujeto a pruebas, modificaciones y actualizaciones.
Con la programación podemos hacer prácticamente cualquier cosa.
Hay programas para:
• Controlar robots.
• Vehículos autónomos.
• Programas que ayudan en el diagnóstico médico analizando miles de datos.
• Videojuegos y películas de animación o efectos especiales de las películas.
• Aplicaciones móviles, sitios y Aplicaciones Web que usan millones de personas diariamente.
PROGRAMA

Un programa es una secuencia de instrucciones que especifican como llevar a cabo un cómputo.
Puede tratarse de algo matemático, como resolver un sistema de ecuaciones o encontrar las raíces de un polinomio
pero puede ser también una tarea como encontrar y reemplazar un texto en un documento o algo visual, por ejemplo,
procesar una imagen o reproducir un video.
Existe un conjunto de características que cumplen todos los programas:
• Entrada: obtener información del teclado, un archivo, una red u otro dispositivo.
• Salida: mostrar información en una pantalla, grabarla en un archivo o enviarla a través de la red, etc.
• Matemática: llevar a cabo operaciones matemáticas básicas tales como suma o multiplicación
• Ejecución condicional: controlar si se cumple una condición y ejecutar el código apropiado.
• Iteración: llevar a cabo repetidamente una misma acción, usualmente con alguna.
Cada programa que alguna vez hemos utilizado, no importa cuán complicado sea está compuesto por alguna de estas
características o su combinación.
Podemos pensar en programar como el proceso de dividir una gran y compleja tarea en subtareas más pequeñas hasta
que las subtareas sean lo suficientemente simples como para parecerse a estas instrucciones básicas.
Un programa está compuesto de cientos de Algoritmos.
ALGORITMOS
Según el diccionario de la R.A.E,
Un algoritmo es un conjunto ordenado y finito de operaciones que permite hallar la solución de un problema.
Prácticamente convivimos con distintos algoritmos toda la vida, que permiten resolver desde los más triviales
problemas de la vida cotidiana como la secuencia de pasos para:
• Atarnos los cordones
• Seguir una receta de cocina.
• Procedimientos rutinarios de trabajo
• Protocolos de evacuación de un edificio ante una contingencia.
Programar entonces no es ni más ni menos que “decirle” a la computadora que debe ejecutar un algoritmo.
En general, los algoritmos deben cumplir las siguientes condiciones:
• Debe existir un único punto de inicio y (al menos) un fin.
• Un algoritmo debe tener una cantidad finita de pasos.
• Los pasos del algoritmo deben ejecutarse en tiempo finito.
• Las órdenes deben ser ejecutables: Tienen que ser operaciones básicas que la computadora pueda realizar.
También pueden ser procedimientos complejos, pero definidos en base a operaciones básicas y otros
procedimientos, que puedan ser ejecutados.
• Las instrucciones deben ser precisas, no pueden ser ambiguas: Una orden o instrucción dada a una
computadora solo puede ser interpretada de una única manera.
En el proceso de desarrollo de software, el diseño de los algoritmos es una parte fundamental ya que establece la
secuencia de pasos lógicos, acciones y decisiones que posteriormente deberá ejecutar la computadora.
Los algoritmos diseñados son independientes de los distintos lenguajes de programación y de las arquitecturas de
cómputo, y constituyen descripciones de alto nivel de abstracción, que en una etapa posterior pueden codificarse en
el lenguaje deseado.
Esto permite trabajar sobre lo que debe hacer un programa sin que importen los detalles de cómo está codificado ni
con qué lenguaje, yendo de lo más general a lo más particular.
ALGORITMOS - FUNDAMENTOS Y DEFINICIONES

Existen tres conceptos fundamentales con los deberemos familiarizarnos, son los Datos, las Variables y las Funciones
de Entrada y Salida (E/S o en inglés I/O).

• Datos
Los conceptos vistos sobre los algoritmos hasta el momento giran en torno a las instrucciones o pasos que se deben
ejecutar para cumplir un determinado objetivo. Sin embargo, la figura principal en el mundo de los algoritmos
informáticos es la información, o los datos a través de los cuales esta se materializa.

• Entradas y salidas
Podemos pensar en los algoritmos como bloques que procesan información que tienen como materia prima un
conjunto de datos de entrada, los cuales son manipulados por el algoritmo, y a partir de los cuales entrega otro
conjunto de datos de salida.
Cuando se requiere diseñar o analizar un algoritmo es importante identificar cuáles son los datos de entrada y de
salida.
Los datos de entrada pueden provenir de diversas fuentes:
• Valores previamente almacenados en la memoria principal.
• Periféricos de entrada (teclado, mouse, red, disco, escáner).
Los datos de salida son los que el algoritmo envía a un periférico de salida del sistema de cómputo. Por ejemplo:
monitor, impresora, parlantes, red, disco, etc. o cualquier dato producido por el algoritmo que luego de finalizado
queda en memoria principal a disposición de otros programas.
• Variables:
Tanto los datos de entrada/salida como el resto de los datos auxiliares que requiera un algoritmo para cumplir su
objetivo, se almacenan en la memoria principal de la computadora, cada uno en un lugar (dirección de memoria)
particular de la misma y ocupando un bloque de una cantidad determinada de esta memoria (medida en bytes).
A cada uno de estos bloques de memoria donde se guarda un dato se lo conoce como variable.
COMPUTADORAS
Una computadora es un dispositivo electrónico que almacena y procesa datos.
Una computadora incluye hardware y software. El hardware es lo visible, son los elementos físicos de una computadora
y el software provee lo invisible, las instrucciones que controlan el hardware y lo hacen llevar a cabo tareas específicas.
Conocer acerca del hardware de una computadora no es esencial para programar pero puede ayudar a un mejor
entendimiento de los efectos que tienen las instrucciones de un programa sobre la computadora y sus componentes.
Una computadora consiste principalmente en los siguientes componentes:
• Unidad central de proceso (CPU).
• Memoria principal.
• Dispositivos de almacenamiento (discos, pendrives, CDs, etc.).
• Dispositivos de entrada (teclados, mouse, gamepads).
• Dispositivos de salida (monitores e impresoras).
• Dispositivos de comunicación (placas de red).
Los componentes de una computadora están interconectados por un subsistema llamado bus.
Podemos pensar en el bus como un sistema de rutas que conecta los componentes de una computadora.
Los datos y la corriente eléctrica fluyen a través del bus de un componente de la computadora hacia la otro.
El las Computadoras Personales (PCs) el bus está integrado en la placa madre o motherboard que es una placa de
circuitos que conecta todos los componentes de la PC.
UNIDAD CENTRAL DE PROCESO
La Unidad Central de Procesamiento (CPU) es el cerebro de la computadora. Recupera las instrucciones desde la
memoria y las ejecuta.
Un CPU tiene usualmente dos componentes: unidad de control y unidad aritmética/lógica.
• La unidad de control coordina las acciones de los demás componentes.
• La unidad aritmética-lógica lleva a cabo operaciones numéricas (adición, sustracción, multiplicación y división)
y operaciones lógicas (comparaciones).
Los CPUs de hoy día están compuestos de pequeños chips semiconductores de silicio que contienen millones de
diminutos interruptores eléctricos que se conocen con el nombre de transistores, utilizados para procesar información.
Cada computadora tiene un reloj interno que emite pulsos electrónicos a intervalos constantes.
Estos pulsos son utilizados para controlar y sincronizar el ritmo de las operaciones.
• Un reloj a velocidades más altas permite que más instrucciones sean ejecutadas en un período de tiempo
dado.
• La unidad de medida en la que se expresa la velocidad del reloj es en Hertz (Hz) siendo 1Hz equivalente un
pulso por segundo. En la actualidad las velocidades de los procesadores se expresan en Gigahertz (GHz). Los
nuevos procesadores corren alrededor de los 3 GHz.
Los CPUs originalmente fueron construidos con un único núcleo.
Un núcleo es una parte del procesador que lleva a cabo la lectura y ejecución de las instrucciones.
Para incrementar el poder de procesamiento los fabricantes producen CPUs que contienen múltiples núcleos. Un CPU
multinúcleo es un componente único con dos o más núcleos independientes.
BITS Y BYTES
Antes de continuar analizando los componentes de una computadora vamos a ver cómo la información (datos y
programas) son almacenados en una computadora.
Una computadora es en realidad un conjunto de interruptores. Cada interruptor tiene dos posibles estados: encendido
o apagado.
Entonces, almacenar información en una computadora se reduce a establecer una secuencia de interruptores.

• Si un interruptor está encendido el valor es 1 y si el interruptor está apagado entonces el valor es 0.


• Estos 0s y 1s son interpretados como dígitos en un sistema de números binarios llamados bits (del inglés binary
digits).
Información de distintos tipos, tal como números y caracteres, son codificados como series de bits.
Como programadores, no tenemos que preocuparnos de codificar y decodificar la información en cada paso,
• Esta conversión la realiza automáticamente la computadora, basándose en el esquema de codificación.
Un esquema de codificación es un conjunto de reglas que establecen cómo la computadora traduce los caracteres y
números en información con la cual puede trabajar.
La mayoría de los esquemas traduce cada carácter en una cadena de bits predeterminadas.
En el esquema de codificación ASCII, por ejemplo, el carácter C es representado como 01000011 en 1 byte.
La mínima unidad de información en una computadora es un byte. Un byte está compuesto por ocho bits.
Un pequeño número tal como el 3 puede ser almacenado en un único byte. Para almacenar un número que no cabe
en un único byte, la computadora utiliza muchos bytes.
La capacidad de almacenamiento de una computadora se mide en bytes y múltiplos de bytes, tal como:
• Un kilobyte (KB) equivale a 1.000 bytes.
• Un megabyte (MB) equivale a 1 millón de bytes.
• Un gigabyte (GB) es igual a 1.000 millones de bytes.
• Un terabyte (TB) es igual a 10.000 millones de bytes.
Un documento de texto típico puede "pesar" unos 20KB. Entonces:
• Un documento de 50 páginas pesa 1MB.
• Un documento de 50,000 páginas pesa 1 GB.
• Una película en alta definición de apróx. 2 horas de duración puede pesar 8GB
• Para almacenar 20 películas se requieren 160GB.
MEMORIA
La memoria principal de una computadora consiste en una secuencia ordenada de bytes para almacenar tanto
programas como datos con los que los programas trabajan.
La memoria principal puede considerarse como el área de trabajo de un programa en ejecución.
Para ser ejecutado por la CPU un programa y sus datos deben ser movidos a la memoria de la computadora.
Cada byte de la memoria principal tiene una dirección única. La dirección es utilizada para ubicar el byte para
almacenar y recuperar los datos.
Dado que los bytes en memoria pueden ser accedidos en cualquier orden, la memoria también puede ser referida
como memoria de acceso aleatoria o (RAM).
Las computadoras personales usualmente tienen al menos 4GB de RAM pero es más común que tengan entre 8 o 16GB
disponibles.
En términos generales a mayor cantidad de memoria RAM que tiene la computadora, más rápido puede operar pero
hay límites para esta regla.
Un byte de memoria nunca está vacío, pero su contenido inicial puede ser que no tenga sentido para nuestros
programas. El contenido actual de un byte de memoria se pierde cuando se coloca en él nueva información.
Al igual que los CPUs, las memorias están hechas de chips semiconductores de silicio que tienen millones de
transistores en su superficie. Comparados con los chips de las CPUs los chips de las memorias son menos complicados,
más lentos y menos costosos.
DISPOSITIVOS DE ALMACENAMIENTO
La memoria RAM de la computadora guarda la información de manera volátil.
• Esto quiere decir que cualquier información que haya sido guardada en la memoria se pierde cuando se
desconecta la energía del equipo.
Los programas y la información son persistidos de manera permanente en dispositivos de almacenamiento.
Cuando es realmente necesario procesarlos son movidos hacia la memoria RAM y/o a la memoria del CPU para ser
procesados.
• Esto funciona mucho más rápido que trabajar directamente con los dispositivos de almacenamiento.
Existen tres distintos tipos de dispositivos de almacenamiento:
• Unidades de Discos Magnéticos
• Unidades de Discos ópticos
• Unidades de almacenamiento USB .
SISTEMA OPERATIVO
El Sistema Operativo es el programa más importante que se ejecuta en una computadora. administra y controla todas
las actividades que en ella tienen lugar.
Los sistemas operativos de propósito general más populares son Windows, Linux y Mac OS.
Los programas de aplicación tales como procesadores de texto o navegadores Web no pueden ejecutarse a no ser que
exista un sistema operativo instalado y ejecutándose en la computadora.
Las principales tareas que lleva a cabo un Sistema Operativo son:
• Controlar y monitorear las actividades del sistema.
• Alojar y asignar recursos del sistema.
• Programar operaciones: multiprogramación, multihilo y multiproceso.
LENGUAJES DE PROGRAMACIÓN
Un lenguaje de programación es un conjunto de símbolos (alfabeto) y un conjunto de reglas para combinar dichos
símbolos que se usan para expresar programas puedan ser entendidos por computadoras.
Constan de un léxico, una sintaxis y una semántica.
• Léxico: Conjunto de símbolos permitidos o vocabulario.
• Sintaxis: Reglas que indican cómo realizar las construcciones del lenguaje.
• Semántica: Reglas que permiten determinar el significado de cualquier construcción del lenguaje.
En la actualidad existen cientos de lenguajes de programación que permiten escribir programas en distintos ámbitos.
Cada uno de ellos fue creado para cumplir con un propósito determinado.
Podemos llegar a preguntarnos... ¿Cuál es el mejor lenguaje de programación?

• Lo cierto es que cada lenguaje tiene sus fortalezas y debilidades.


Podemos clasificar los lenguajes de programación por su nivel:
• Lenguajes de bajo nivel: código máquina.
• Lenguajes de nivel medio: Assembler (asm) o lenguaje ensamblador.
• Lenguajes de alto nivel: C, C++, Java, Python, JavaScript, etc.
El lenguaje de bajo nivel, es directamente el lenguaje propio de la máquina.
El mismo está íntimamente relacionado con el hardware, y normalmente está formado por largas secuencias de ceros
y unos que indican a la computadora las instrucciones básicas a ejecutar que conforman un programa.
El código máquina resulta difícil de manejar para los seres humanos. Por este motivo, con el avance y difusión de las
computadoras, se empezaron a utilizar abreviaturas para representar las operaciones básicas de las computadoras,
que es lo que se conoce como lenguaje ensamblador.
Por ejemplo; el programador que escribe la instrucción de ADD 0184 para una máquina IBM antigua, tendría que haber
escrito:
• 000100000000000000000000000010111000
Características del lenguaje máquina y ensamblador:
• Dependientes del procesador.
• Requiere el conocimiento del hardware del procesador.
• Utiliza instrucciones muy elementales, que realizan operaciones básicas.
• Los programas ocupan poca memoria logrando alta velocidad de ejecución.
Es de destacar que los lenguajes de bajo y medio nivel requieren un amplio conocimiento del hardware y además se
necesitan muchas instrucciones para llevar a cabo tareas sencillas.
Con el objeto de acelerar el proceso de desarrollo de programas, surgieron los lenguajes de alto nivel, que permiten
realizar tareas más complejas con instrucciones simples.
Es así, que para traducir estos programas de alto nivel a código máquina surgieron los compiladores y los intérpretes.
Características de los Lenguajes de alto nivel:
• Independientes del procesador.
• Permiten desconocer detalles del hardware.
• Escritura cercana al lenguaje natural.
• Poseen librerías con funciones de entrada/salida, matemáticas, etc.
PARADIGMAS DE PROGRAMACIÓN
Un paradigma es una teoría o conjunto de teorías cuyo núcleo es aceptado por todos los integrantes que usan ese
paradigma, y que sirve como modelo para resolver problemas utilizándolo.
En el mundo del desarrollo de software un paradigma de programación indica el método y la forma en la que se deben
estructurar y organizar las tareas que debe realizar el programa que se está desarrollando.
Algunos de los paradigmas más populares son:
• Paradigma imperativo: se caracteriza por enfocarse en cómo se pretenden realizar los cálculos por medio de
instrucciones secuenciales para formar algoritmos que resuelvan una tarea específica.
o El paradigma imperativo es el más utilizado en los lenguajes de programación, de forma única o en
conjunción con otros paradigmas.
o Ejemplos cotidianos de este paradigma se pueden encontrar en las recetas de cocina o en cualquier
guía paso a paso.
• Paradigma procedural: derivado del paradigma imperativo, añadiendo funcionalidades extra como la creación
de procedimientos o funciones que pueden ser llamadas en las secuencias de código como si fueran
instrucciones simples.
o De esta forma los programas están organizados y modularizados en funciones específicas que no
tienen por qué residir en el mismo archivo. Esto favorece la modularización y organización del código.
• Paradigma orientado a objetos: este paradigma es uno de los más populares junto con el imperativo y se basa
en encapsular las entidades principales del programa en objetos que pueden contener tanto datos como
comportamiento (métodos para interactuar con otros datos u otros objetos).
o Este paradigma es especialmente útil, puesto que favorece la modularidad, el encapsulamiento, la
reusabilidad y la escalabilidad de cualquier programa.
o Muchas implementaciones de este paradigma cuentan con la herencia de objetos. Implementan este
paradigma los lenguajes de programación Java, C++, Rust, Python o JavaScript.
• Paradigma declarativo: Está basado en el desarrollo de programas especificando o "declarando" un conjunto
de condiciones, proposiciones, afirmaciones, restricciones, ecuaciones o transformaciones que describen el
problema y detallan su solución. La solución es obtenida mediante mecanismos internos de control, sin
especificar exactamente cómo encontrarla.
o Los lenguajes de programación declarativos describen el resultado final deseado, en lugar de mostrar
todos los pasos de trabajo. Para alcanzar el objetivo se determina automáticamente la vía de solución.
o Como la programación declarativa no determina el "cómo", sino que funciona a un nivel de abstracción
muy alto, este paradigma deja margen para la optimización. Si se ha desarrollado un procedimiento
de ejecución mejor, el algoritmo integrado lo encuentra y lo aplica.
Los distintos lenguajes declarativos se pueden subdividir, a su vez, en dos paradigmas, el de la programación lógica y
el de la programación funcional.
o Programación lógica
▪ Basada en las lógicas formales. Todo programa escrito en un lenguaje de programación lógico
es un conjunto de sentencias lógicas, expresando hechos y reglas sobre un dominio.
▪ Los lenguajes de programación lógica utilizan una estrategia de búsqueda para producir los
resultados en función de los hechos y reglas. Por ejemplo: backtracking.
o Paradigma funcional: se basa en funciones matemáticas que se centran en los cambios de estado del
programa por medio de la mutación de variables.
▪ Tiene su origen en el cálculo lambda y presenta características muy potentes, como la
recursividad, el uso de funciones de orden superior o el uso de funciones puras que definen
que la misma función, con los mismos argumentos, siempre debe devolver el mismo resultado
(evitando cualquier efecto colateral). Ejemplos: Haskell, Miranda y otros híbridos como Lisp,
Scala y OCalm.
CICLO DE VIDA DEL DESARROLLO DE SOFTWARE
El proceso de desarrollo o ciclo de vida del software (SDLC) es una secuencia estructurada y bien definida de etapas
que deben seguirse para desarrollar un producto software. Es una de las ramas de estudio de la Ingeniería de Software.
Existen distintos modelos que describen el proceso de desarrollo, los cuales plantean distintas etapas y formas de
proceder para que un equipo de programadores lleve a cabo el desarrollo de un programa.
MODELO EN CASCADA
El modelo de desarrollo en cascada es el más clásico, el primero en aparecer y a partir del cual surgen las técnicas más
modernas. En este modelo se plantea seguir una serie de etapas de manera secuencial, las cuales se detallan a
continuación:
Análisis de requisitos
• Se analiza la problemática a resolver y las necesidades de los futuros usuarios del programa, convirtiéndolos en
requisitos concretos que debe cumplir el programa.
Diseño de la solución
• En esta etapa se estudian posibles opciones de implementación para el software que hay que construir, así como
decidir la estructura general del mismo.
• Se trata de una etapa compleja y su proceso debe realizarse de manera iterativa.
• Se realizan diagramas de las distintas partes del software (módulos, funciones).
• Se determina la manera en que se representará y manejará la información de interés (variables, constantes,
estructuras de datos).
• Se establece la forma de interacción del usuario (interfaz, entradas y salidas).
• Se diseñan los algoritmos de cada módulo.
Codificación y pruebas unitarias

• En esta etapa se debe elegir las herramientas adecuadas, un entorno de desarrollo que facilite el trabajo y un
lenguaje de programación apropiado para el tipo de software a construir.
o Esta elección dependerá tanto de las decisiones de diseño tomadas como del entorno en el que el software
deba funcionar.
• Se escribe el código fuente de los algoritmos de los distintos módulos en un lenguaje de programación y se
documentan los componentes del software.
• En la medida que se van construyendo los componentes se prueban de manera aislada. Esto puede ser
programando pruebas automatizadas o haciéndolas manualmente.
o Se controla que las salidas sean las esperadas para cada una de las diferentes entradas.
Integración, validación y verificación del programa
• Se integran los distintos módulos ya depurados, conformando el programa ejecutable.
• Se ejecuta el programa y se verifica el cumplimiento de los distintos requisitos generados en la fase de análisis.
• Se corrigen los errores encontrados.
Implementación o despliegue
• Implica todas las actividades que hacen que un software esté disponible para su uso.
• Se instala el software en los equipos que corresponda (servidores, dispositivos y/o PCs usuario).
• Puede requerir la instalación y/o configuración de software adicional.
• La capacitación y soporte de usuarios es de suma importancia en esta etapa.
Mantenimiento
• Corrección de fallas detectadas durante el uso y de necesidades cubiertas parcialmente.
• Se implementan mejoras de eficiencia.
Sobre la aplicación del modelo en cascada
• Seguir a rajatabla el modelo en cascada no es eficiente, especialmente cuando esperamos concluir toda la fase de
codificación para comenzar las pruebas. Lo cual retrasa la detección de errores de funcionamiento y dificulta su
identificación en el código.
• Suele ser conveniente entremezclar estas dos fases, de manera tal de ir codificando, ejecutando y probando de a
partes pequeñas de código. Así es posible identificar con más facilidad las secciones de código con errores y
solucionarlos a la brevedad.
OTROS MODELOS
Modelo repetitivo
• Este modelo guía el proceso de desarrollo de software en repeticiones. Así, proyecta el proceso de desarrollo de
modo cíclico repitiendo cada paso después de cada ciclo en el proceso de ciclo de vida del software.
Modelo en espiral
• El modelo en espiral es una combinación de los modelos anteriores donde se tiene en cuenta el riesgo. De esta
forma, se comienza fijando los objetivos y las limitaciones al empezar cada repetición. En la etapa siguiente se
crean los modelos de prototipo del software, que incluye el análisis de riesgo. Posteriormente se usa un modelo
estándar para construir el software y finalmente se prepara el plan de la próxima repetición.
Modelo en V

• Uno de los grandes problemas del modelo en cascada es que solo se pasa a la siguiente fase si se completa la
anterior y no se puede volver atrás si hay errores en etapas posteriores. Así, el modelo en V da más opciones de
evaluación del software en cada etapa.
• En cada fase se crea la planificación de las pruebas y los casos de pruebas para verificar y validar el producto en
función de los requisitos de la misma. De esta manera, verificación y validación van en paralelo.

UNIDAD II: PYTHON


Python es un lenguaje de programación interpretado de alto nivel.

En 1989, Guido van Rossumm (holandés de 24 años) comenzó como hobby el desarrollo de Python, con el objetivo de
mejorar la interfaz de usuario del Sistema Operativo Amoeba.

En un principio, Python iba a ser un lenguaje de programación pequeño que sucedería al lenguaje ABC que
desarrollaban en CWI (Centrum Wiskunde & Informatica) (instituto donde se desempeñaba van Rossum) incorporando
algunas características adicionales y que ayudara a interactuar mejor con el sistema operativo.

La primera versión de Python fue lanzada en febrero de 1991 con el número de versión 0.9.0.
El nombre del lenguaje proviene de la afición que tenía van Rossum a la serie de televisión Monty Python´s Flying
Circus y no de algo relacionado con el mundo de los reptiles.

• Entre 2005 y finales de 2012 van Rossum trabajó en Google, entre otros proyectos, contribuyendo en el desarrollo
de Python.
• Entre 2012 y 2019 en Dropbox.
• En 2019 se jubiló y en 2020 volvió a trabajar incorporándose a Microsoft.

CARACTERÍSTICAS

Python es un lenguaje de alto nivel, de propósito general, multiparadigma principalmente imperativo, orientado a
objetos y funcional, de tipado dinámico y fuertemente tipado a nivel de lenguaje de programación.

Ventajas:

• Sintaxis sencilla, simple y clara: permite desarrollar programas de forma intuitiva.


o Esta característica hace que leer un programa escrito en Python sea muy parecido a leer un texto anglosajón.
o Ejemplos que motivan la claridad son:
▪ Los bloques lógicos se definen utilizando identación en vez de utilizar caracteres de apertura y cierre de
bloque como { y } ( usado en lenguajes como Java, JavaScript o C).
▪ Las expresiones simples no necesitan uso de paréntesis como pasa en lenguajes como JavaScript.
▪ Para la separación de instrucciones se utiliza el salto de línea en vez del comúnmente utilizado carácter
“;”, aunque también permite utilizarlo.
▪ Posee un sistema de recolección de basura que permite que el desarrollador se despreocupe de la gestión
de memoria y que el lenguaje se pueda centrar en otros aspectos de alto nivel.
• Interpretado: significa que no es necesario compilar los programas cada vez que se hace un cambio en el código.
o Esto presenta una gran ventaja frente a los lenguajes compilados (C o C++) y aumenta considerablemente la
velocidad de desarrollo de aplicaciones.
o Por otro lado, el ser un lenguaje interpretado permite que el código sea independiente del hardware en el
que se ejecuta, y ayuda a que el lenguaje sea multiplataforma gracias al uso de su máquina virtual.
• Baterías incluidas: posee multitud de herramientas en la librería estándar que ayudan a realizar un sinfín de
aplicaciones sin necesidad de utilizar bibliotecas de terceros.
o Python también permite la integración con otros lenguajes de programación, ya sea importando código
dentro de otros lenguajes o permitiendo ejecutar código de otros lenguajes en Python.
o Así, podemos tener código Python ejecutando código C, C++, .Net o Java, y viceversa. Usando diferentes
técnicas, el código Python se puede transcompilar en otro lenguaje (como JavaScript) u otros lenguajes pueden
ejecutar código Python haciendo uso de subprocesos u otras técnicas.
• Multiplataforma: lo que permite que se pueda ejecutar y programar en multitud de plataformas, desde los
sistemas operativos más tradicionales de ordenadores personales, como Windows, Linux o Mac OSX, hasta
dispositivos electrónicos más exóticos como teléfonos o relojes inteligentes, pasando por consolas de videojuegos.
• Libre, de Código abierto y gratuito: es decir que sin licencias restrictivas Python puede ser usado, copiado,
estudiado, y modificado de cualquier forma.
o El código de Python es compartido libremente y se alienta a la comunidad de programadores que mejoren el
diseño del software.
o Las distintas versiones de Python pueden descargarse desde el sitio Web oficial:
https://www.python.org/downloads/source/
• Comunidad: Python cuenta con extensa documentación y una enorme comunidad.
o La comunidad oficial “Python Software Foundation” (PSF): https://www.python.org/psf/
o La evolución de Python se rige por la aprobación/implementación de propuestas de mejora conocidas con el
nombre de PEP. que siguen un proceso de aprobación que participa e involucra a los miembros de la
comunidad.

Debilidades:

Al igual que cualquier otro lenguaje de programación, Python también tiene puntos débiles:
• Lentitud: en muchas ocasiones se considera que los programas desarrollados en Python son “lentos” en
comparación con los tiempos de ejecución de lenguajes compilados.
o El origen de esta afirmación reside en que se trata de lenguaje interpretado y no poseer por defecto un
compilador JIT (del inglés Just in – Time), lo que haría que se compilase el programa escrito en Python y
optimizasen más los tipos de datos.
o Aún así, en Python 3 se han hecho muchas mejoras de rendimiento de los tipos de datos y se ha mejorado
notablemente este aspecto.
o No obstante, existen librerías que permiten marcar porciones de código para ser compiladas en tiempo de
ejecución o la opción de utilizar CPython, que permite escribir código C compatible con Python e integrarlo de
forma natural para mejorar la velocidad de procesamiento.

VERSIONES

A lo largo de su historia Python ha sufrido numerosos cambios y hoy en día sigue recibiéndolos continuamente a través
de las PEP. A continuación, se nombran las principales versiones con los cambios más destacados:

• Versión 0.9 (1991): primera versión de Python publicada por van Rossum. Contaba con muchos componentes
actuales como listas, diccionarios, conceptos de orientación a objetos, cadenas de caracteres y otras
características.
• Versión 1.0 (1994): se introducen conceptos de programación funcional.
• Versión 1.6 (2000): se añade licencia compatible con GPL (GNU General Public License).
• Versión 2.7 (2010): Es la última versión de la rama 2.X y se incluyen algunas de la ya empezada a desarrollar
versión3.X. En noviembre de 2014 se anuncia la versión2.X y que dejará de tener soporte a principios de 2020,
invitando a los usuarios a migrar activamente a la versión 3.
• Versión 3.0 (2008): se hacen cambios en cuestiones principales del lenguaje, quitando redundancia de código e
introduciendo grandes incompatibilidades con la versión 2.
• Versión 3.9 (2020): se añaden múltiples funcionalidades y se borran algunas presentes por retrocompatibilidad
con la versión 2.
• Versión 3.10.2 (13 de enero de 2022): última versión del lenguaje.

INTÉRPRETE DE PYTHON

Python es un lenguaje de programación interpretado, lo que significa que el código fuente no necesita ser compilado
al código máquina específico del hardware donde se ejecuta, sino que se ejecuta directamente en cualquier sistema
que tenga instalada la máquina virtual de Python.

Cuando se instala Python en una máquina, este tiene, como mínimo dos componentes:

• El intérprete y
• La librería estándar (módulo, funciones, constantes, tipos, tipos de datos, excepciones, etc.).

Dependiendo de la implementación de Python, el intérprete puede estar escrito en C, Java, .net, etc.

Se podría definir el intérprete como un programa que se encarga de ejecutar otros programas.

A continuación se ahondará en ello:

• El código fuente, que se compone de archivos de texto plano que tienen una gramática específica (que se
denomina lenguaje Python), con una extensión concreta (.py) y estructurados de una forma precisa.
• Por otro lado, se encuentran los ficheros de byte code, que son el resultado de una compilación rápida que se
efectúa justo antes de comenzar la ejecución. El código escrito en byte code está listo para ser ejecutado en
cualquier máquina virtual de Python.
• Por último, se encuentra la máquina virtual de Python (PVM – Python Virtual Machine), que es la encargada de
ejecutar los archivos que tienen el byte code. Por lo tanto, la parte que sí es dependiente del hardware utilizado
es la máquina virtual.
• Lo que se denomina intérprete de Python es el programa completo que analiza el código fuente, genera los ficheros
compilados y ejecuta el código usando la máquina virtual.
Cabe destacar algunas peculiaridades del byte code:

• Los archivos que contienen el byte code tienen una extensión .pyc (Python compiled).
• Los archivos no son necesarios para la ejecución del programa, dado que, si no se pueden generar por algún
motivo (por falta de espacio o de permisos de escritura), el byte code será generado e insertado en memoria
directamente, sin crearse en ficheros guardados en el sistema operativo.
• Un programa en Python que tenga los archivos .pyc generados no necesita tener el código fuente, por lo que se
puede ahorrar espacio de disco borrando los códigos fuente solo ejecutando los .pyc (solo se recomienda en
sistemas con grandes restricciones de espacio).
• El intérprete de Python es inteligente a la hora de generar los .pyc, y ya se han generado los ficheros .pyc y no ha
habido cambios en el fichero fuente, no realiza ninguna compilación, simplemente usa los ficheros ya compilados,
agilizando así el proceso de iniciar la aplicación.

IMPLEMENTACIONES DE PYTHON

Cuando se habla de la implementación de Python, normalmente se hace referencia a la implementación usando C


denominada CPython.

• No obstante, el intérprete puede ser implementado en otros lenguajes. Las diferencias entre implementaciones
están, principalmente, en la habilidad de usar librerías escritas en algún lenguaje específico.

CPython:

• Es la implementación original del lenguaje y la más utilizada, programada en ANSI C.


• El intérprete genera byte codes desde archivos de código fuente para ejecutarlos en la máquina virtual de Python,
y esta los ejecuta.
• Si un sistema operativo tiene una versión de Python preinstalada, lo más seguro es que la implementación sea
CPython.
• Es el estándar, siempre se mantiene actualizada, soporta la interoperabilidad con librerías escritas en C y
normalmente es muy rápida en tiempo de ejecución comparada con las demás implementaciones.
• Otras implementaciones: Jython, PyPy, IronPython.

PRIMER PROGRAMA EN PYTHON

Es tradición, que el primer programa que escribimos cuando aprendemos un nuevo lenguaje de programación se llame
“Hola Mundo!”, porque esas son las palabras que se van a mostrar “Hola Mundo”.

En Python se hace así:

» print (‘Hola Mundo!’)

Esto es un ejemplo de cómo la sentencia print (imprimir en inglés), aunque no imprime nada en papel, muestra por
pantalla los resultados. En este caso los resultados son las palabras
– Hola Mundo!

Las comillas en el programa marcan el principio y el final de un texto que debe ser mostrado pero no aparecen en el
resultado.

Los paréntesis indican que print es una función.

En Python 2, la instrucción print no llevaba paréntesis:

» print ‘Hola Mundo!’

OPERACIONES ARITMÉTICAS

Después del ‘Hola Mundo!’ el siguiente paso son las matemáticas.

Python nos provee de operadores. Se tratan de símbolos especiales que representan computaciones como adición o
multiplicación.
Los operadores +, -, * llevan a cabo suma, resta y multiplicación. En los siguientes ejemplos los vemos en
funcionamiento:

» 40 + 2 » 43 – 1 »6*7

42 42 42

El operador / realiza la división de dos números

– » 84 / 2

– 42.0

Vemos que a diferencia de las operaciones anteriores el resultado es 42.0 en vez de 42. Discutiremos esto más
adelante.

Finalmente, con ** realizamos exponenciación.

– » 6** 2 + 6

– 42

VALORES Y TIPOS DE DATOS

Un valor es una de las cuestiones más básicas con las que un programa trabaja puede ser una letra o un número.
Algunos valores que vimos hasta el momento son 2, 42.0 y ‘Hola Mundo’.

Estos valores pertenecen a distintos tipos de datos: 2 es un entero, 42.0 es un número de punto flotante y ‘Hola
Mundo’ es un string o cadena de caracteres (se llama así porque las letras están enlazadas unas a otras).

Si no sabemos de qué tipo es un valor la función type() nos puede decir:

– » type(2)

– <class 'int'>

– » type(42.0)

– <class 'float'>

– » type('Hola Mundo!')

– <class 'str'>

En los resultados mostrados anteriormente la palabra “class” (clase en inglés) se usa en un sentido de clasificación o
categoría.

EJECUTANDO PROGRAMAS EN PYTHON DESDE ARCHIVOS

Para desarrollar un programa en Python no basta con usar nuestros comandos en “modo calculadora”.

Necesitamos guardar lo que queremos hacer en un archivo y ejecutar el intérprete.

Para ello:

1. Utilizando un editor de textos, creamos un nuevo archivo con el contenido de nuestro programa y luego lo
guardamos con extensión .py.
2. Abrimos una consola de comandos y nos posicionamos en el directorio donde quedó el archivo.
3. Ejecutamos Python escribiendo en la consola: python hola.py o simplemente py hola.py

COMENTARIOS

En la medida que los programas se vuelven más grandes y complejos, se vuelven más difíciles de leer.
Muchas veces vamos a encontrarnos con una porción de código que nos va a llevar tiempo darnos cuenta qué hace o
el motivo por lo qué lo hace.

Por esta razón es una buena idea agregar notas a los programas para explicar en lenguaje natural lo que está haciendo
el programa. Estas notas son llamadas comentarios y comienzan con el símbolo #.

– # calculo la cantidad de milisegundos en una hora

– 60 * 60 * 1000

Todo lo que aparece a partir del símbolo # hasta el final de la línea es Ignorado por Python y no tiene efectos en la
ejecución del programa.

UNIDAD III: TIPOS DE DATOS


VARIABLES

Una de las características más poderosas de los lenguajes de programación es la habilidad de manipular variables.

Una variable es un nombre que se refiere a un valor. Al nombrar valores guardados en memoria, el desarrollador
puede hacer referencia a ellos no solo cuando son creados, sino más adelante en el programa.

Las variables también permiten manipular valores.

Sentencias de asignación

• Crea una nueva variable y le da un valor:

mensaje = ‘Y ahora… algo completamente diferente’


n = 17
pi = 3.1415926535897932

Este ejemplo hace tres asignaciones. La primera asigna un string a una nueva variable con nombre mensaje, el segundo
le asigna 17 a n y el tercero el (aproximado) valor de π a pi.

NOMBRES DE VARIABLES

Los programadores generalmente eligen nombres para sus variables que tengan algún significado y que muestren para
qué se usan esas variables.

• Los nombres de las variables pueden ser de cualquier longitud.


• Pueden contener letras y números pero no pueden comenzar con un número.
• Está permitido utilizar letras en mayúscula pero es convención utilizar solo letras en minúscula.
• El símbolo infraguión _, puede aparecer en el nombre. Es común que se use en nombres con múltiples
palabras, tales como tu_nombre, o velocidad_auto.

Si se le asigna un nombre inválido a una variable obtendremos un error de nombre ilegal.

– » 10messi = ‘Lionel’
– SyntaxError: invalid syntax
– » nacho@novello = ‘nacho’
– SyntaxError: invalid syntax
– » class = ‘Programación1’
– SyntaxError: invalid syntax

Algunas cuestiones importantes para tener en cuenta:


• Python es sensible a mayúsculas y minúsculas. Por ejemplo, tanto:
• Variable_Uno y variable_Uno
• Son identificadas como variables diferentes.

Cuando elegimos un nombre para nuestros archivos… tampoco es recomendable usar palabras reservadas.

Para nombrar variables en Python se utiliza la sintaxis de los identificadores y la convención de usar snake_case la cual
define que los nombres deben estar en su forma minúscula o mayúscula (dependiendo de si se tratan de variables
locales o constantes, respectivamente) y unidos por un ‘_’ o infraguión.

Pueden contener números pero siempre tienen que empezar con una letra

PALABRAS RESERVADAS

La palabra class es una de las palabras reservadas de Python. El intérprete utiliza palabras reservadas para reconocer
la estructura del programa, y no pueden ser utilizadas como nombres de variables.

No es necesario memorizar el listado de palabras reservadas. La mayoría de los IDE nos muestran en un color diferente
las palabras reservadas.

Si intentamos utilizar una palabra reservada como nombre de variable nos vamos a enterar!

EXPRESIONES Y SENTENCIAS

Una expresión es una combinación de valores, variables y operadores. Un valor es por sí mismo considerado una
expresión y también una variable. Todas las siguientes son expresiones válidas:

– » 42

– 42

–»n

– 17

– » n + 25

– 42

Cuando se escribe una expresión en el prompt el intérprete la evalúa lo que significa que encuentra el valor de la
expresión. Por ejemplo, n tiene valor 17 y n + 25 tiene el valor 42.

Una sentencia es una unidad de código que tiene un efecto, como crear una variable o mostrar un valor.

– » n = 17 # asigna un valor a n

– » print(n) # muestra por pantalla el valor de n

Cuando escribimos una sentencia el intérprete la ejecuta. Es decir, hace lo que dice la sentencia.

ORDEN DE OPERACIONES

Cuando una expresión contiene más de un operador, el orden de evaluación, depende del orden de las operaciones.
Para los operadores matemáticos, Python sigue las convenciones matemáticas. El acrónimo PEMDAS es una forma útil
de recordar estas reglas:

• Paréntesis: tiene el más alto nivel de precedencia y pueden ser utilizados para forzar a que una expresión se
evalúe en el orden deseado. Dado que las expresiones en paréntesis se evalúan primero, 2 * (3 – 1) es 4 y (1 +
1)**(5 - 2) es 8. Se puede también utilizar paréntesis para facilitar la lectura como en (minuto * 100) / 60,
incluso si la intención no es cambiar la precedencia.
• Exponenciación: tiene el siguiente nivel de precedencia, así que 1 + 2**3 es 9, no 27 y 2 * 3**2 es 18 no 36.
• Multiplicación y División: tienen mayor nivel de precedencia que adición y sustracción. Así que 2 * 3 - 1 es 5,
no 4 y 6 + 4 / 2 es 8 no 5.
• Operadores con igual nivel de precedencia: son evaluados de izquierda a derecha (excepto exponenciación):
grados / 2 * pi, la división sucede primero y el resultado es multiplicado por pi. Para dividir 2 por pi se puede
usar paréntesis o escribir: grados / 2 / pi.

No es difícil recordar la precedencia de los operadores. Si no podemos darnos cuenta con simplemente mirar el código
de la expresión, entonces deberíamos usar paréntesis para que quede más claro.

OPERACIONES CON STRINGS

En general no se pueden llevar a cabo operaciones matemáticas sobre strings, incluso si los strings parecen números,
las siguientes expresiones son inválidas:

‘asado’ - ‘fútbol’ ’pizza’ / ‘cerveza’ ’fresco’ * ‘batata’

Pero las dos excepciones son + y *.

El operador + lleva a cabo la operación de concatenación, esto significa que dos strings se juntan extremo con extremo.
Por ejemplo:

» primero = ‘Corona’
» segundo = ‘virus’
» primero + segundo
Coronavirus

El operador * puede funcionar también en strings para indicar repetición si uno de los operandos es un string y el otro
un entero. Por ejemplo: ‘Tock’*3 es ‘TockTockTock’.

El uso de + y * tiene la misma analogía que suma y multiplicación. Así como 4*3 es el equivalente a 4+4+4 esperamos
que ‘Tock’*3 sea ‘Tock’ + ‘Tock’ + ‘Tock’.

¿Hay alguna propiedad que la sumatoria no comparta con la concatenación de strings?

DEPURACIÓN DE PROGRAMAS – DEBUGGING

Todos los programadores cometemos errores. En la jerga se conocen con el nombre de bugs (insectos/bichos).

Encontrar los errores hasta lograr que nuestros programas hagan lo que queremos nos va a hacer sentir enojados,
abatidos o avergonzados. Tenemos que prepararnos para estas situaciones.

Un enfoque que puede ayudar es pensar en las computadoras como nuestras empleadas que como todas las personas
tiene ciertas fortalezas y debilidades.

• Fortalezas: velocidad y precisión.


• Debilidades: falta de empatía e incapacidad de tener una visión general del problema o tarea encomendada.

Si pensamos que somos el jefe… nuestra tarea será potenciar esas habilidades y mitigar las debilidades y por otra parte
encontrar la forma de comprometernos con el problema sin que nuestras reacciones no interfieran con nuestra
habilidad de trabajar.
Aprender a depurar puede ser frustrante pero es una habilidad valorada y muy útil en muchas actividades más allá de
la programación.

Hay tres tipos de errores que pueden ocurrir en un programa. Es necesario distinguirlos para rastrearlos más
rápidamente:

Error de sintaxis: “sintaxis” hace referencia a la estructura del programa y las reglas sobre la estructura. Por ejemplo,
los paréntesis deben coincidir en apertura y cierre. Por eso (1 +2) es correcto pero 8) no.

• Si se presenta algún error de sintaxis el programa no puede continuar. Durante nuestra primera etapa como
programadores vamos a pasar mucho tiempo tratando con errores de sintaxis. Luego con más experiencia se
cometerán menos errores y los encontraremos más rápido.

Errores de tiempo de ejecución: El segundo tipo de error no aparece hasta que el programa empieza a ejecutarse.
Estos errores también se llaman excepciones porque comúnmente indican que algo excepcional ha sucedido.

• Los errores en tiempo de ejecución son extraños en programas simples así que nos los vamos a encontrar más
adelante en el curso.

Errores de semántica: Si hay algún error de semántica, nuestro programa va a ejecutarse sin arrojar ningún mensaje
de error pero no va a hacer lo correcto. Va a hacer otra cosa. Específicamente, va a hacer lo que le indicamos.

• Identificar errores de semántica puede ser difícil porque hay que buscar hacia atrás mirando los resultados del
programa e intentando identificar qué es lo que está haciendo.

TIPOS DE DATOS

En la vida cotidiana estamos rodeados de datos de diferentes tipos:

• Existen datos numéricos:


o Estadísticas de compras y ventas de los productos.
o Kilómetros por hora de un automóvil.
o Latitud y longitud.
• En forma de cadenas de caracteres:
o Pequeñas, como siglas.
o Enormes como un libro completo.
• En forma de fechas, que ayudan a organizar calendarios.

Un Tipo de Datos define una representación interna, un conjunto de valores válidos y las operaciones que se pueden
realizar sobre esos valores.

En esta asignatura se verán los tipos de datos presentes en el núcleo de Python o integrados.

Python provee un amplio abanico de tipos de datos fácilmente instanciables e intuitivos que permiten que cualquier
desarrollador pueda enfocarse en qué construir y no en cómo hacerlo.

LITERALES, VARIABLES Y TIPOS DE DATOS

Cuando los valores se intentan trasladar al ámbito de la computación y de los lenguajes de programación, se hace uso
de la memoria de un sistema, que es la herramienta que permite almacenarlos y manejarlos de forma eficiente.

En Python los tipos de datos son objetos y es el propio intérprete el que se encarga de saber dónde se ubican en la
memoria y cómo acceder a ellos.

Por este motivo, a la hora de desarrollar aplicaciones no es necesario dedicarle mucho esfuerzo a la gestión de
memoria.
Conceptualmente los objetos en Python se pueden ver como dos componentes:

• Una referencia, que guarda la dirección de memoria en la que está alojado el dato.
• Un contenedor que representa el almacenamiento del objeto guardado en sí, el cual contiene información
relevante como el tipo de dato y la información que alberga.

CONSTANTES LITERALES

Cuando hablamos de constantes literales estamos haciendo referencia al resultado de las expresiones o las propias
formas primitivas de cada dato que ocupan un espacio en la memoria y pueden ser accedidas por el intérprete.

Ejemplos de constantes literales:

• Números: 1, 24, 54.


• Cadenas de caracteres: ‘cadena de prueba’, ‘Python’, ‘Martes’

Todos los objetos en Python tienen un identificador que define dónde se encuentra en memoria.

Esta relación de identificador con posición o posiciones específicas de memoria es interna al intérprete de Python, por
lo que, a pesar de tener un identificador, no se puede saber con facilidad en qué zona de la memoria está alojado el
valor que representa.

LITERALES, VARIABLES E IDENTIFICADORES

Si dos valores tienen el mismo identificador, entonces, ambos valores son exactamente el mismo, lo que permite
ahorrar espacio en la memoria. No obstante, esto conlleva un inconveniente:

• Si se cambia el valor de referencia del identificador, el cambio afectará a todos los objetos que lo usen.

Es decir si escribimos ‘Hola!’ en múltiples lugares del programa el valor propiamente dicho se almacenará en la
misma dirección de memoria.

• Para saber el identificador de un objeto se puede usar la función id().


• Para acceder a la información que contiene el objeto con ese identificador, se puede hacer uso de la librería
ctypes.

TIPOS BOOLEANOS

En Python, los conceptos de verdadero y falso están presentes y modelados como booleanos con dos valores
constantes: True y False (con la primera letra en mayúscula).

La función bool() permite convertir cualquier valor en un valor booleano:


>>> print(bool(True), bool(False))
True False
>> print(bool(0), bool(0j), bool(''), bool(None), bool(set())
False False False False False
>> print(bool(1), bool(-1), bool('casa'), bool(24))
True True True True

Todos los valores en Python tienen asociada una noción de verdad. Algunos son evaluados como falso:

• Las constantes None y False


• Los valores numéricos interpretados por cero: 0, 0.0, 0j
• Los objetos vacíos: '' , "" , () , dict(), set() range(0), []

TIPOS BOOLEANOS – OPERACIONES

Las operaciones lógicas con booleanos son tres: or, and y not, como se muestra en la siguiente tabla:

Las operaciones and y or siempre devuelven uno de los operandos, no simplemente True o False.

La operación and devuelve el último de sus elementos y la operación or, el primero que cumpla con el cortocircuito
lógico:

» 324 and 89 and 2 dá como resultado 2

» False and 21 dá como resultado False

» 23 or 'casa' dá como resultado 23

» True and 0 and 90 dá como resultado 0

TIPOS BOOLEANOS – OPERADORES – CORTOCIRCUITO LÓGICO

El cortocircuito lógico es una propiedad que implementa Python para la evaluación de expresiones y que, además,
ayuda a hacerlas más eficientes puesto que no necesita evaluar las expresiones completas.

Durante la evaluación de una expresión and se encuentra un elemento que es False, se detiene la ejecución
(cortocircuita la ejecución) y devuelve ese valor.

Hace lo mismo con las expresiones or, pero con los elementos que devuelvan True.

TIPOS NUMÉRICOS

En el núcleo de Python existen tres tipos numéricos definidos que permiten expresar los números enteros, los números
de coma flotante (números reales) y los números complejos en forma sencilla, así como operar con ellos.

Operadores:

• Existen operaciones numéricas compartidas por todos los tipos numéricos de Python, Además, se pueden
combinar valores de tipos numéricos diferentes en cuyo caso prevalecerá el más general:
ENTEROS

Los enteros son valores numéricos más simples e intuitivos son del tipo int.

Ejemplos:

-1
100
+123
5_000_000

La expresión: 05 (anteponiendo cero) arroja error de sintaxis.

En Python los enteros pueden ser tan grandes como sea necesario, dado que no tienen un número máximo fijo
asignado.

La función int() toma un argumento de entrada y nos devuelve un valor entero equivalente.

» int(True) → 1
» int(False) → 0

La conversión de números de punto flotante retorna un entero perdiéndose la parte fraccionaria.

» int(4.8) → 4

NÚMEROS DE PUNTO FLOTANTE

Los números de punto o coma flotante (o números reales) forman parte del conjunto de tipos numéricos
implementado en Python y permite realizar operaciones de forma fácil y sencilla gracias a las operaciones que hay
disponibles en el núcleo.

Ejemplos:

» 5. → 5.0
» 5.0 → 5.0
» 05.0 → 5.0

Podemos escribir en notación científica:

» 5e0 → 5.0
» 5.0e1 → 50.0
» 5.0e10 → 50000000000.0

La función que nos permite convertir cualquier valor en un número de punto flotante es float().
COMPARACIONES

En Python los objetos se pueden comprar entre sí con los ocho tipos de operadores básicos:

STRINGS O CADENAS DE CARACTERES

Los strings no son como los enteros, números de punto flotante o booleanos.

Un string es una secuencia, es decir, una colección ordenada de valores. En este caso de caracteres.

Un carácter es la unidad más pequeña en un sistema de escritura. Incluye letras, dígitos, símbolos, puntuación e incluso
espacios en blanco o directivas como saltos de línea.

A diferencia de otros lenguajes, los strings en Python son inmutables. Es decir, no puede cambiar una cadena. Nos
queda entonces, copiar partes de strings a otro string para obtener el mismo efecto.

Alternativas para la creación de cadenas:


» 'Snap' → ‘Snap’ # Comillas simples
» "Crackle" → ‘Crackle’ # Comillas dobles
» '''Boom!''' → ‘Boom!’ # Triple comillas simples
» """Quich!"""→ ‘Quich!’ # Triple comillas dobles
» str(4.5) → ‘4.5’ # Conversión de valores a string

El propósito principal de las múltiples alternativas para crear strings es que los mismos puedan contener comillas
simples o dobles dentro del texto:

» "Calle O' Connor" → “Calle O’ Connor”


» '"Hoy puede ser un gran día!"' → ‘“Hoy puede ser un gran día!”’

Los strings con triple comillas son útiles para crear strings multilínea.

» """Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam placerat, sem
ut luctus consectetur, ex elit cursus orci, eget tempus purus arcu vel risus."""

» 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n Nullam placerat, sem
ut luctus consectetur, ex elit cursus orci, eget tempus purus arcu vel risus.'

La función print() remueve las comillas de los strings e imprime su contenido.


» print(“We”, ‘will’, “rock”, ‘you’) We will rock you →

Existe el string vacío. Que si bien no tiene ningún carácter es completamente válido.
» '' → ''
» "" → ''
» '''''' → ''
SECUENCIAS DE ESCAPE

Supongamos que en un string queremos escribir un “enter” o salto de línea. ¿Cómo hacemos? ¿Y si quiero hacer
tabulaciones?

Python nos permite expresar caracteres que tienen un significado especial (y que de otra forma serían muy difíciles de
expresar) utilizando secuencias de escape.

Expresamos una secuencia de escape con el carácter \ (barra invertida o back slash).

Podemos hacer saltos de línea o “enters” con \n dentro del string:

– » november_rain ="Nothin' lasts forever\nAnd we both know hearts can change\nAnd


it's hard to hold a candle\nIn the cold November rain"
– » print(november_rain)
– Nothin' lasts forever
– And we both know hearts can change
– And it's hard to hold a candle
– In the cold November rain

Las tabulaciones se hacen con \t

– » print("Sweet Child\t O' mine")


– Sweet Child O’ mine

INDEXACIÓN UTILIZANDO []

Para obtener un único carácter de un string debemos, justo después el nombre del string, y entre corchetes debemos
especificar su posición o índice.

• La primera posición (más a la izquierda) accesible es 0, la siguiente 1 y así sucesivamente.


• La última posición (más a la derecha) puede ser accedida usando -1, yendo más a la izquierda -2, -3 y así
sucesivamente.
• Los índices válidos de un string de longitud x, son enteros desde -x hasta +x-1.

– » letras = ‘abcdefghijklmnopqrstuvwxyz’
– » letras[0] → ‘a’
– » letras[1] → ‘b’
– » letras[-1] → ‘z’
– » letras[-2] → ‘y’
– » letras[5] → ‘f’

● Si especificamos un índice mayor a la longitud del string. Tendremos un error:

– » letras[100]
– Traceback (most recent call last):
– IndexError: string index out of range

SUBSTRINGS CON SLICE

Un substring es el nombre con el que se conoce a una parte de un string.

Podemos extraer un substring de un string utilizando un slice (del inglés rebanada).


Definimos un slice usando corchetes, una posición de inicio, una de fin y opcionalmente un paso entre ellos.

• Se pueden omitir algunos de los valores.


• El slice incluirá los caracteres coincidentes con inicio y el fin menos uno.

[:] extrae la secuencia completa desde el principio a final.

[inicio:] especifica desde inicio hasta el final.

[:fin] especifica desde el principio al final menos uno.

[inicio:fin] indica desde el principio hasta el fin menos 1

[inicio:fin:paso] extrae desde inicio hasta el fin menos 1, omitiendo la cantidad de caracteres
especificadas en paso.

Si el paso es positivo los desplazamientos se incrementan desde inicio hacia la derecha siendo el primero 0, luego 1, y
así sucesivamente y -1, -2 y así sucesivamente desde el final hacia la izquierda en caso de tratarse de un paso negativo.

Ejemplos:

» letras = ‘abcdefghijklmnopqrstuvwxyz’
» letras[:] → ‘abcdefghijklmnopqrstuvwxyz’ # el string completo.
» letras[20:] → 'uvwxyz' # desde 20 hasta el final.
» letras[12:15] → 'mno' # desde 12 hasta 14.
» letras[-3:] → 'xyz' # los últimos 3 caracteres.
» letras [::7] → ‘ahov’ # de principio a fin salteando de a 7 caracteres.
» letras[::-1] → 'zyxwvutsrqponmlkjihgfedcba' # empieza al final y con paso
negativo llega al principio.

LONGITUD

Hasta ahora hemos utilizado algunos caracteres de puntuación especiales para tratar con strings como el operador +.

Python tiene muchas funciones integradas (porciones de código con nombre) que pueden llevar a cabo determinadas
operaciones.

La función len() (del inglés length o longitud) cuenta la cantidad de caracteres en un string.

» len(letras)
26
» vacio = ''
» len(vacio)
0

UNIDAD IV: FUNCIONES Y MÓDULOS


MODULARIZACIÓN Y DISEÑO DESCENDENTE DE PROGRAMAS

Una de las técnicas fundamentales para resolver un problema es dividirlo en problemas más pequeños llamados
subproblemas.

Estos problemas pueden ser divididos repetidamente en problemas más pequeños hasta que sean solucionados.

La técnica de dividir el problema principal en subproblemas se denomina frecuentemente, divide y vencerás.


El método de diseñar la solución de un problema principal obteniendo las soluciones de sus subproblemas se denomina
diseño descendente (top-down design) debido a que se comienza en la parte superior con un problema general y se
diseñan soluciones específicas a sus subproblemas.

• Cada subproblema es deseable que sea independiente de los restantes y se denomina módulo.
• El problema principal se resuelve con el programa principal (también llamado conductor del programa) y los
subproblemas (módulos) mediante subprogramas.

Un subprograma realiza una tarea concreta que se describe con una serie de instrucciones.

La resolución de un problema comienza con una descomposición modular y luego nuevas descomposiciones de cada
módulo en un proceso denominado refinamiento sucesivo (stepwise).

Ejemplo:

• Dadas las puntuaciones de una clase, ordenar las puntuaciones (notas) en orden decreciente; a continuación
visualizar la calificación alcanzada basada en la puntuación.

FUNCIONES

En el contexto de programación, una función es un nombre que se le asigna a una secuencia de sentencias que llevan
a cabo un cómputo.

Una función nos permite definir un bloque de código reutilizable que se puede ejecutar muchas veces dentro de
nuestro programa.

Las funciones son bloques de código que se pueden reutilizar simplemente llamando a la función.

Esto permite la reutilización de código simple y elegante sin volver a escribir explícitamente secciones de código
(reduce el número total de líneas).

Esto hace que el código sea más legible, facilita la depuración y limita los errores de escritura.

LLAMADAS A FUNCIONES

Ya previamente vimos invocaciones a funciones cuando usamos la función type(42).

» type(42) → <class ‘int’>

El nombre de la función es type. La expresión entre paréntesis es llamada el argumento de la función. El resultado,
para esta función es el tipo del argumento.

Es común decir que la función "toma" un argumento y "retorna" un resultado. El resultado también es llamado valor
de retorno.

Python nos provee de funciones que pueden convertir valores de un tipo en otro. La función int toma cualquier valor
y lo convierte en un entero siempre que pueda, si no lo puede hacer entonces arrojará un ValueError.

» int('32') → 32
» int('Hello') → ValueError: invalid literal for int(): Hello

int convierte valores de punto flotante en enteros, pero no puede redondearlos, simplemente trunca la parte decimal.
Entonces:

» int(3.9999) 3 →
» int(-2.3) -2 →

Finalmente, str convierte su argumento en un string.

» str(32) → '32'
» str(3.15159) → '3.14159'
FUNCIONES MATEMÁTICAS

Python tiene un módulo que nos provee de las funciones matemáticas más comunes.

Un módulo es un archivo que contiene una colección de funciones relacionadas. Antes de que podamos usar las
funciones de un módulo, tenemos que importarlo con la sentencia import.

» import math

Esta sentencia crea un objeto de tipo módulo que se llama math. Si se muestra, se puede obtener información sobre
el mismo.

» math → <module 'math' (built-in)>

El objeto módulo contiene las funciones y variables definidas en el módulo. Para acceder a una de las funciones, se
tiene que especificar el nombre del módulo y el nombre de la función, separados por el símbolo punto '.'.

» ratio = signal_power / noise_power


» decibels = 10 * math.log10(ratio)
» radians = 0.7
» height = math.sin(radians)

En el ejemplo usamos math.log10 para computar la relación señal/ruido en decibeles (asumiendo que signal_power
y noise_power son variables definidas) . El módulo math también provee de la función log, que computa logaritmos
en base e.

COMPOSICIÓN

Una de las características más importantes de los lenguajes de programación es su habilidad de tomar pequeños
elementos del programa como variables, expresiones y sentencias y combinarlos.

Por ejemplo, el argumento de una función puede ser cualquier tipo de expresión incluso las que incluyan operadores
aritméticos:

x = math.sin(degrees / 360.0 * 2 * math.pi)

Podemos incluir también llamadas a otras funciones:


x = math.exp(math.log(x+1))

Casi en cualquier lugar que podemos poner un valor, se puede escribir una expresión.

La única excepción es que si tenemos una sentencia de asignación solamente a la izquierda puede haber un nombre
de variable. Caso contrario tendremos un error de sintaxis.

» minutes = hours * 60 # correcto


» hours * 60 = minutes # incorrecto! → SyntaxError: can't assign to operator

CREANDO NUESTRAS PROPIAS FUNCIONES

Python nos permite crear nuestras propias funciones. Una definición de función específica el nombre para la nueva
función y una secuencia de sentencias que se van a ejecutar cuando la función sea invocada. Ejemplo:

def imprimir_letra():
print(“Hey Jude, don't make it bad.”)
print(“Take a sad song and make it better.”)

La palabra reservada que indica que comienza la definición de una función es def. El nombre de la función es
imprimir_letra.
Las reglas para los nombres de función son los mismas para los nombres de variables.

Los paréntesis vacíos luego del nombre de la función indican que no recibe ningún argumento.

La primera línea de la definición de la función se llama cabecera; el resto cuerpo. La cabecera tiene que finalizar con
el carácter “:” (dos puntos) y el cuerpo de la función tiene que estar identado. El cuerpo puede contener cualquier
número de sentencias.

La sintaxis para invocar funciones creadas por nosotros es la misma que para las funciones integradas.

imprimir_letra()

Una vez que hemos definido una función podemos usarla dentro de otras funciones.

Por ejemplo, para repetir la letra varias veces podemos escribir una función llamada repetir_letra:

def repetir_letra():
imprimir_letra()
imprimir_letra()

Y luego llamar a la función repetir_letra:

» repetir_letra()
Hey Jude, don't make it bad.
Take a sad song and make it better.
Hey Jude, don't make it bad.
Take a sad song and make it better.

DEFINICIONES Y USOS

Si juntamos los fragmentos de código vistos anteriormente el programa entero se vería así:

def imprimir_letra():
print(“Hey Jude, don't make it bad.”)
print(“Take a sad song and make it better.”)
def repetir_letra():
imprimir_letra()
impimir_letra()
repetir_letra()

La definición de las funciones se ejecuta tal cual el resto de las sentencias, no generan ninguna salida y el efecto que
tienen es crear un objeto función.

Las sentencias dentro de la función no se ejecutan hasta que la función es llamada.

La función debe crearse antes de ser invocada.

FLUJO DE EJECUCIÓN

Para asegurar que una función se defina antes de usarse por primera vez, tenemos que conocer el orden de las
sentencias que contiene, lo que se conoce con el nombre de flujo de ejecución.

La ejecución siempre comienza por la primera sentencia del programa. Las sentencias son ejecutadas una a la vez de
arriba hacia abajo.
Las definiciones de funciones no alteran el flujo de ejecución del programa.

Una llamada a una función es como un desvío en el flujo de ejecución. En vez de ir hacia la siguiente sentencia, el flujo
salta al cuerpo de la función, ejecuta las sentencias allí y luego vuelve para retomar donde se había dejado.

Mientras se encuentra en medio de una función, es posible que el programa deba ejecutar las sentencias de otra
función. Luego, mientras ejecuta esa nueva función, ¡el programa podría tener que ejecutar otra función más!

Python se encarga por nosotros de llevar nota de donde es necesario retomar la ejecución luego de una función es
invocada y cuando se llega al fin del programa, lo termina.

PARÁMETROS Y ARGUMENTOS

Algunas funciones que vimos requieren argumentos. Por ejemplo, cuando llamamos a la función math.sqrt pasamos
un número como argumento.

Algunas funciones requieren más de un argumento. Por ejemplo, math.pow, necesita la base y el exponente.

Dentro de la función, los argumentos son asignados a variables que se llaman parámetros. Aquí la definición de una
función que acepta argumentos:

def imprimir_dos_veces(nombre):
print(nombre)
print(nombre)

La función asigna el argumento a un parámetro que se llama nombre. Cuando la función es invocada, imprime el valor
del parámetro dos veces. Funciona con cualquier valor que pueda imprimirse por pantalla.

» imprimir_dos_veces(‘Martín’)
Martín
Martín
» imprimir_dos_veces(42)
42
42
» imprimir_dos_veces(math.pi)
3.14159265359
3.14159265359

También podemos hacer composición utilizando funciones integradas:

» imprimir_dos_veces(‘Nacho’ * 4)
Nacho Nacho Nacho Nacho
Nacho Nacho Nacho Nacho
» imprimir_dos_veces(math.cos(math.pi))
-1
-1

El argumento es evaluado antes que la llamada a la función, así que los ejemplos de las expresiones. ‘Nacho’ * 4 y
math.cos(math.pi) se evalúan una sola vez.

También podemos usar una variable como argumento:


– » larita = ‘Lari, lari!!!’
– » imprimir_dos_veces(larita)

El nombre de la variable que pasamos como argumento (larita) no tiene nada que ver con el nombre del parámetro
nombre. No importa qué nombre tenga el argumento en desde donde se hizo la invocación.

ALCANCE DE VARIABLES Y PARÁMETROS

Cuando creamos una variable dentro de una función su alcance es local, esto quiere decir que solo existe dentro de la
función. Por ejemplo:

def concat_imprimir(part1, part2):


cat = part1 + part2
imprimir_dos_veces(cat)

Esta función toma dos argumentos, los concatena, e imprime los resultados dos veces. Ejemplo:

linea1 = 'Línea 1'


linea2 = 'Línea 2'
concat_imprimir(linea1, linea2)

Cuando concat_imprimir termina, la variable cat es destruida. Si intentamos imprimir su valor obtendremos una
excepción:
» print(cat) → NameError: name 'cat' is not defined

Los parámetros son locales a la función. Por ejemplo, fuera de imprimir_dos_veces, no hay nada como cat.

FUNCIONES QUE RETORNAN VALORES

Algunas funciones que hemos usado, tales como las funciones matemáticas, retornan valores (en algunos contextos
se llaman funciones que retornan valores o fructíferas).

En funciones, como imprimir_dos_veces, se lleva a cabo una acción pero NO se retorna un valor.

Estas funciones son llamadas funciones que no retornan valores.

Cuando llamamos a una función que retorna valores, casi siempre tenemos que hacer algo con el resultado. Por
ejemplo, puede ser que queramos asignarlo a una variable o utilizarlo como parte de una expresión.

» calculo = (math.sqrt(25) + 1) / 2

Cuando llamamos a cualquier función en modo interactivo, Python muestra un resultado.

Pero en un script si llamamos a una función que devuelve resultados el valor de retorno se pierde.

Las funciones que retornan vacío puede ser que muestren algo en la pantalla o tengan algún efecto pero no tienen
valor de retorno. Si asignamos el resultado a una variable, obtendremos un valor especial que es None.

• None no es lo mismo que ‘None’. None es un valor que tiene su tipo especial
• » type(None) -> <class ‘NoneType’>

Cuando invocamos a una función que retorna valores generalmente utilizamos el resultado para asignárselo a una
variable o como parte de una expresión.

e = math.exp(1.0)
height = radius * math.sin(radians)

A continuación vamos a programar la función area() que devuelve el área de un círculo dado su radio:
def area(radio):
calculo = math.pi * radio**2
return calculo

La semántica de la sentencia return es: “Devolver inmediatamente a quien invocó la expresión que sigue”.

La expresión puede ser tan complicada como queramos. Por ejemplo, podemos omitir la variable calculo del ejemplo
anterior.

def area(radio):
return math.pi * radio**2

Hay varias razones por las cuales vale la pena dividir un programa en funciones:

• Crear una nueva función nos da la oportunidad de nombrar un grupo de sentencias lo que hace más fácil de
leer y depurar nuestros programas.
• Una función hace el programa más pequeño eliminado código repetitivo. Más tarde si tenemos que hacer un
cambio solo tenemos que hacerlo en un único lugar.
• Dividir un programa largo en funciones nos permite depurar las partes que lo componen una a la vez y luego
ensamblarlo en un todo que funcione.
• Las funciones bien diseñadas, generalmente son utilizadas por muchos programas. Una vez que escribimos y
depuramos podemos reutilizar.

UNIDAD V: ESTRUCTURAS DE CONTROL


Una estructura de control es una sentencia de control y las sentencias cuya ejecución ésta controla.

Es un bloque de código que permite agrupar instrucciones de manera controlada.

Todos los lenguajes de programación tienen un conjunto mínimo de instrucciones que permiten especificar el control
propio del algoritmo que se requiere implementar.

• Este conjunto mínimo debe contener estructuras para la Secuencia, Decisión, Selección e Iteración.

Secuencia

• La estructura de control más simple está representada por una sucesión de instrucciones (por ejemplo
asignaciones), en la que el orden de ejecución coincide con el orden físico de aparición de las instrucciones.
• La implementación de la estructura de control secuencia se logra simplemente ubicando una instrucción
debajo de la anterior.

DECISIÓN – EJECUCION CONDICIONAL

Cuando programamos, casi siempre necesitamos controlar condiciones y cambiar el comportamiento del programa de
acuerdo a si se cumplen o no. Las estructuras de control condicionales nos dan esta habilidad.
if x > 0:
print(‘x es positivo’)

La expresión booleana después de la palabra reservada if es llamada condición. Si es True (verdadero), la sentencia
identada que le sigue se ejecuta. Caso contrario, nada sucede.

El if tiene la misma estructura que la definición de una función: un encabezado seguido por un cuerpo identado. Las
sentencias como esta se llaman declaraciones compuestas.

• No hay límite para el número de sentencias que pueden aparecer en el cuerpo de un bloque if, pero tiene que
ser al menos una.
• Ocasionalmente, es útil tener un cuerpo sin sentencias (para guardar espacio para algo que vamos a agregar
más tarde).
• En ese caso, podemos escribir la palabra reservada pass que no hace nada.

if x < 0:
pass # Aquí falta manejar qué pasa cuando x es menor que 0.

EJECUCION ALTERNATIVA

Una segunda forma de la sentencia if es la ejecución alternativa, donde hay dos posibilidades y una condición que
determina cuál se ejecuta.

La sintaxis es así:

if x % 2 == 0:
print ('x es par')
else:
print('x es impar')

El resto de la división entera de x por 2 es 0 cuando x es par. En ese caso el programa muestra el mensaje: x es par.

En caso que la condición sea False (falso), el segundo conjunto de sentencias se ejecuta.

Dado que la condición debe ser True o False, exactamente una de las alternativas se ejecuta. Las alternativas son
llamadas ramas, porque como si fueran ramas donde se bifurca el flujo de ejecución.

CONDICIONES ENCADENADAS

A veces hay más de dos posibilidades y necesitamos más de dos ramas. Una forma de expresar un cómputo de este
tipo es encadenar condiciones.

if x < y:
print ('x es menor que y')
elif x > y:
print ('x es mayor que y')
else:
print('x e y son iguales')

elif es una abreviación de “else if”.

• Otra vez, exactamente sólo una de las ramas se va a ejecutar.


• No hay límite para la cantidad de sentencias que pueden aparecer dentro de un bloque elif.
• Si hay una cláusula else, tiene que estar al final, no es obligatorio que exista.

if opcion == 'a':
dibujar_a()
elif opcion == 'b':
dibujar_b()
elif opcion == 'c':
dibujar_c()

Cada condición es controlada en orden. Si la primera es False, la siguiente es controlada y así sucesivamente.
Si uno de ellos es True, la rama correspondiente se ejecuta y finaliza el bloque.

Si más de una condición es verdadera, solo la primera se ejecuta.

CONDICIONES ANIDADAS

Un condicional puede ser también anidado dentro de otro. Podemos escribir el ejemplo tratado anteriormente de esta
forma:

if x == y:
print('x e y son iguales')
else:
if x < y:
print ('x es menor que y')
else:
print('x es mayor que y')

El condicional exterior contiene dos ramas. La primera contiene una única sentencia simple. La segunda contiene otra
sentencia if que tiene sus propias dos ramas.

Esas dos ramas son también sentencias simples, sin embargo, podrían haber sido sentencias condicionales también.

Puede parecernos que la identanción de las sentencias hace fácil de leer la estructura, pero los condicionales anidados
se vuelven difíciles de leer muy rápido. Es una buena idea evitarlos lo más que podamos.

Los operadores lógicos nos pueden ser una solución para evitar los condicionales anidados. Por ejemplo, podemos
reescribir el siguiente código usando un condicional simple:

if 0 < x:
if x < 10:
print('x es un número positivo de un sólo dígito')

La instrucción print se ejecuta sólo si pasamos las dos condiciones, así que podemos obtener el mismo efecto utilizando
un operador and:

if 0 < x and x < 10:


print ('x es un número positivo de un sólo dígito')

Para este tipo de condiciones, Python provee una opción más concisa:
if 0 < x < 10:
print ('x es un número positivo de un sólo dígito')

OPERADOR TERNARIO

El operador ternario es una herramienta muy potente que muchos lenguajes de programación tienen.

En Python es un poco distinto a lo que sería en los lenguajes de la familia de C, pero el concepto es el mismo.

Se trata de una cláusula if, else que se define en una sola línea utilizada que retorna un valor si se cumple una condición
y otro en caso que no se cumpla.

En vez de escribir:

a = 10, b = 10
if b != 0:
c = a / b
else:
c = -1

Escribimos:

c = a/b if b != 0 else -1

SELECCIÓN – MULTIPLES ALTERNATIVAS CON MATCH

En este tipo de estructuras de control se nos permite ejecutar diferentes secciones de código dependiendo de una
condición.

La sentencia de control match/case toma un objeto y verifica si coincide con uno o más patrones. Por último lleva a
cabo una acción si se encontraron coincidencias.

Por ejemplo:

match variable:
case 1:
print(“Seleccionó 1”)
case 2:
print(“Seleccionó 2”)
case _:
print(“No entró en ninguno”)

Donde si el valor de variable coincide con el de uno de los valores que siguen a la palabra reservada case, entonces,
las sentencias dentro del bloque case se ejecutan.

El símbolo _ al final, es un comodín, se seleccionará en caso que no existan coincidencias con los valores expresados
en las entradas case previas.

Python carecía hasta la versión 3.10 de una estructura de control del tipo switch/case como existe en la familia de
lenguajes de C.

Quedaban como alternativas entonces hacer bloques if/elif o utilizar diccionarios junto con expresiones lambda.

En el caso de usar bloques if/elif, no todos los bloques tienen el mismo tiempo de acceso. Todas las condiciones van
siendo evaluadas hasta que se cumple alguna de ellas y deriva el control a la sentencia siguiente. Imaginemos que
tenemos 100 condiciones.

if variable == 1:
print("1")
elif variable == 2:
print("2")
# ... hasta 100
elif variable == 100:
print("100")
else:
print("x")
El tiempo de ejecución será distinto si la variable es 1 o es 70 por ejemplo:

Si es 1: Se evalúa el primer if, y como se cumple la condición se ejecuta y sale.

Si es 70: Se va evaluando cada condición, hasta llegar al 70. Es decir, tienen que evaluarse 70 condiciones.

REPETICION / ITERACIÓN

Las computadoras comúnmente se utilizan para automatizar tareas repetitivas dado que repetir tareas idénticas o
similares sin cometer errores es algo que a las computadoras hacen excelente.

En programación, se llama iteración a la habilitad de ejecutar un bloque de sentencias de manera repetida.

Hay dos tipos de iteraciones:

• Iteración indefinida: el bloque de código se ejecuta hasta que se cumple alguna condición.
o En Python con un bucle while
• Iteración definida: el número de repeticiones se especifica explícitamente de antemano.
o En Python con un bucle for

RE-ASIGNACION E INCREMENTO/DECREMENTO

Vimos que es posible asignar más de una vez valores a una misma variable.

Una nueva asignación hace que la misma variable haga referencia a un nuevo valor y deje de referenciar al viejo.
» x = 5
» y = 7
» x
5
» x = y
» x
7

La primera vez que mostramos x, tiene valor 5, luego su valor es 7.

Actualización de variables

• Un tipo común de re-asignación es la actualización, donde el nuevo valor depende del anterior.
» x = x + 1
• Esto significa "al valor actual de x sumarle uno, y luego actualizar x con el nuevo valor".
• Incrementar en uno a una variable se llama incremento y restarle uno se llama decremento.

BLOQUE WHILE

La primera estructura de control iterativa que veremos es el bloque while.

A continuación mostramos como podemos hacer una cuenta descendente de números del 10 al 1.
def cuenta_descendente(n):
while n > 0:
print (n)
n = n - 1
print (”It's the final countdown!!! Tarata taaaaa!!!”)

Casi que se puede leer la instrucción while como que si fuese en inglés:

• "Mientras n sea mayor que 0 mostrar el valor de n y luego decrementar n. Cuando se llegue a 0 mostrar It's the
final countdown".

Más formalmente, aquí el flujo de ejecución del bloque while:

1) Determinar si la condición es True o False (verdadera o falsa).


2) Si es False (falsa), salir del while y continuar con la ejecución de la siguiente sentencia.
3) Si la condición es True (verdadera), ejecutar el cuerpo y luego volver al paso 1.

El tipo de flujo es llamado bucle porque el tercer paso vuelve hacia atrás al primer paso.

El cuerpo del bucle tiene que cambiar el valor de una o más variables para que la condición se vuelva falsa en algún
momento y termine el bucle.

En caso que no fuese así, el bucle se repetirá por siempre, lo que se llama bucle infinito.

En el caso de cuenta_descendente() podemos determinar que el bucle finaliza siempre que n sea un entero positivo,
en cada paso se vuelve cada vez más pequeño hasta llegar a 0.

Para otros bucles no es fácil saber. Por ejemplo:


def sequence(n):
while n != 1:
print(n)
if n % 2 == 0: # n es par
n = n / 2
else: # n es impar
n = n * 3 + 1

La condición para este bucle es n != 1, así que si el bucle continua hasta que n es 1.

Con cada iteración, el programa imprime el valor de n y luego controla si es par o impar. Si es par, n es dividido por 2.
Si es impar, el valor de n es reemplazado por n * 3 + 1. Por ejemplo, si el argumento pasado a sequence es 3, los
resultados son 3, 10, 5, 16, 8, 4, 2, 1.

Dado que n a veces se incrementa y a veces se decrementa, no hay una prueba obvia que n en algún momento
alcanzará el valor 1 y termine. Para algunos valores particulares de n, podemos probar que termina. Por ejemplo, si el
valor de inicio es una potencia de dos, entonces el valor de n será par cada vez que se pasa a través del bucle, hasta
que lleguemos a 1.

La pregunta difícil de contestar es cómo podemos probar que termina para todos los valores positivos de n.

Hasta ahora, nadie ha sido capaz de afirmarlo o negarlo: Conjetura de Collatz.

RANGOS O RANGE
Los rangos son secuencias de números enteros no modificables predefinidas. Se crean utilizando la función range, que
también determina el tipo de dato.

Así range (4) genera la siguiente salida:

print(list(range(4)) # después vemos que es list


0
1
2
3

Un rango genera una secuencia de números que van desde 0 por defecto hasta el número que se pasa como parámetro
menos 1.

• En realidad, se pueden pasar hasta tres parámetros separados por coma, donde el primero es el inicio de la
secuencia, el segundo el final y el tercero el salto que se desea entre números.
• Por defecto se empieza en 0 y el salto es de 1. Cabe destacar que los índices pueden ser negativos y tan grandes
como se desee.

Por lo tanto, si hacemos range(5,20,2), se generarán números de 5 a 19 (inclusive) de dos en dos.

Siendo rang1 un rango y num un entero estas son las operaciones soportadas por los rangos:

• rang1.count(num): indica cantidad de ocurrencias de num en el rango. Siempre


el resultado es 1 o 0.
• rang1.index(num): ubicación de num en el rango
• rang1.start: valor de inicio del rango
• rang1.step: permite consultar el paso numérico usado en el rango
• rang1.stop: permite consultar el número en el que el rango dejará de generar
nuevos números.

Los rangos son inmutables y presentan la gran ventaja de que son iteradores (concepto que veremos más adelante en
profundidad), por lo que, cuando se crean, no guardan la información que representan, sino el procedimiento
necesario para generar la secuencia de números. Esto hace que ocupen muy poco espacio y permitan controlar la
memoria utilizada en los programas, ya que van generando los valores de uno en uno y no todos a la vez.

Se puede acceder a un elemento en concreto del rango utilizando un índice y usar operaciones como len() o in e incluso
usar selecciones de subsecuencias.

» rango = range (0, 24, 2)


» rango
range (0, 24, 2)
» 8 in rango
True
» 7 in rango
False
» rango[3]
6

BUCLE FOR

El bucle for de Python tiene algunas particularidades comparado con otros lenguajes de comparación.
El for es un tipo de bucle, similar al while pero con ciertas diferencias.

• La principal es que el número de iteraciones de un for esta definido de antemano, mientras que en un while
no.
• Mientras que en el while la condición es evaluada en cada iteración para decidir si volver a ejecutar o no el
código, en el for no existe tal condición, sino un iterable que define las veces que se ejecutará el código.

En el siguiente ejemplo vemos un bucle for que se ejecuta 5 veces, y donde la variable i incrementa en cada iteración
su valor en 1.
» for i in range(0, 5):
» print(i)
0
1
2
3
4

Es preferible utilizar un bucle for (en vez de while) cuando la cantidad de iteraciones se conoce de antemano o está
definida por las dimensiones de un tipo de datos que soporte operaciones de iteración.

En Python se puede iterar prácticamente todo, como por ejemplo una cadena. En el siguiente ejemplo vemos como la
i va tomando los valores de cada letra.

» for i in "Python":
» print(i)
P
y
t
h
o
n

BREAK

A veces se ejecutan algunas iteraciones de un bucle y nos damos cuenta que no es necesario seguir con las siguientes.
En estas situaciones la sentencia break hace que la ejecución continúe inmediatamente después del bucle.

Por ejemplo, queremos capturar los datos ingresados por el usuario hasta que escriba listo. Podríamos escribir:

while True:
linea = input('Ingrese un texto o "listo" para terminar')
if linea == 'listo':
break
print(linea)
print('Listo!')
La condición del bucle es True, que siempre se va a cumplir, así que el bucle se ejecuta hasta que llega la sentencia
break.

Esta forma de programar los bucles while es común porque podemos controlar si una condición se cumple en cualquier
lugar dentro del bucle (no solo al principio) y podemos expresar que se detenga afirmativamente ("Frená si pasa
esto!") en vez de negativamente ("Hacé esto hasta que pase aquello").

CONTINUE

La palabra reservada continue nos permite terminar la iteración actual y continuar con la siguiente.

Por ejemplo:

for i in "Python":
if i == "t":
continue
print(i)
P
Y
h
o
n

REPRESENTACIÓN DE ALGORITMOS

Para representar un algoritmo debemos utilizar algún método que permita independizar dicho algoritmo del lenguaje
de programación elegido.

Ello permitirá que un algoritmo pueda ser codificado indistintamente en cualquier lenguaje.

Para conseguir este objetivo se precisa que el algoritmo sea representado gráfica o numéricamente, de modo que la
descripción pueda servir fácilmente para su transformación en un programa, es decir, su codificación.

Los métodos usuales para representar un algoritmo son:

1) Diagrama de flujo,
2) Pseudocódigo,
3) Diagrama Nassi-Schneiderman,
4) Lenguaje coloquial,
5) Fórmulas.

Un diagrama de flujo (en inglés flowchart) es una técnica de representación de algoritmos.

• Si bien los diagramas de flujo son antiguos, son la técnica más utilizada a la hora de diseñar y documentar.

Un diagrama de flujo utiliza símbolos (cajas) estándar, normalizados por ANSI (American National Standards
Institute), y describe los pasos de un algoritmo escritos en esas cajas unidas por flechas, denominadas líneas de flujo,
que indican la secuencia en que se debe ejecutar.

SIMBOLOS

Aquí vemos algunos símbolos más comunes de los diagramas de flujo:


EJEMPLOS
RECURSIVIDAD

Sabemos que una función puede llamar a otra función y ésta a su vez a otra, y así sucesivamente; dicho de otro modo,
las funciones se pueden anidar.

Se puede tener:

A llamar_a B, B llamar_a C, C llamar_a D

Cuando se produce el retorno de los subprogramas a la terminación de cada uno de ellos el proceso resultante será:

D retornar_a C, C retornar_a B, B retornar_a A


¿Qué sucedería si dos funciones de una secuencia son los mismos?
A llamar_a A

o bien

A llamar_a B, B llamar_a A

En primera instancia, parece incorrecta. Sin embargo, existen muchos lenguajes de programación donde una función
puede llamarse a sí misma.

La recursividad o recursión es un concepto que proviene de las matemáticas, y que aplicado al mundo de la
programación nos permite resolver problemas o tareas donde las mismas pueden ser divididas en subtareas cuya
funcionalidad es la misma. Dado que los subproblemas a resolver son de la misma naturaleza, se puede usar la misma
función para resolverlos.

Una función recursiva es aquella que se llama repetidamente a sí misma hasta llegar a un punto de salida.

La recursión puede ser utilizada como una alternativa a la repetición o estructura repetitiva.

El uso de la recursión es particularmente idóneo para la solución de aquellos problemas que pueden definirse de modo
natural en términos recursivos.

• Es una herramienta muy potente en algunas aplicaciones, sobre todo de cálculo.

Una función recursiva es similar a una tradicional solo que tiene dos secciones de código claramente divididas:

• La sección en la que la función se llama a sí misma.


• Por otro lado, tiene que existir siempre una condición de terminación en la que la función retorna sin volver
a llamarse. Es muy importante porque de lo contrario, la función se llamaría de manera indefinida.

CUENTA REGRESIVA

Reveamos la solución iterativa de la cuenta regresiva para luego realizar su implementación recursiva.

Implementación Iterativa (usando while)

def cuenta_descendente(n):
while n > 0:
print (n)
n = n - 1
print ("It's the final countdown!!! Tarata taaaaa!!!")

Implementación Recursiva

def cuenta_descedente_rec(n):
if n == 0:
print("It's the final countdown! Tarata taaaa!!!")
else:
print(n)
cuenta_descedente_rec(n - 1)

FACTORIAL

Muchas funciones matemáticas se definen recursivamente. Un ejemplo de ello es el factorial de un número entero n.

Si se observa la fórmula anterior cuando n > 0, es fácil definir n! en función de (n–1)! Por ejemplo, 5:

5! = 5x4x3x2x1 = 120
4! = 4x3x2x1 = 24
3! = 3x2x1 = 6
2! = 2x1 = 2
1! = 1x1 = 1
0! = 1 = 1

En términos generales sería:

def factorial(n):
if n == 0:
return 1
return n * factorial(n-1)

SERIE FIBONACCI

Otro ejemplo típico de una función recursiva es la serie Fibonacci.

Esta serie fue concebida originalmente como modelo para el crecimiento de una granja de conejos (multiplicación de
conejos) por el matemático italiano del siglo XVI, Fibonacci.

La serie es la siguiente: 1, 1, 2, 3, 5, 8, 13, 21, 34 ...

Esta serie crece muy rápidamente; como ejemplo, el término 15 es 610.

La serie de Fibonacci (fib) se expresa así:

fib(1) = 1

fib(2) = 1

fib(n) = fib(n – 1) + fib(n – 2) para n > 2


En Python, una función recursiva que calcula el elemento enésimo de la serie de Fibonacci es:

def fibonacci(n):
if n == 0:
return 0
elif n == 1:
return 1
else:
return fibonacci(n-1) + fibonacci(n-2)

COMPROBACIÓN DE TIPOS

¿Qué sucede si llamamos a factorial y le damos 1.5 como argumento?

» factorial (1.5) → RuntimeError: Maximum recursion depth exceeded

Tiene todo el aspecto de una recursión infinita Pero, ¿cómo ha podido ocurrir?

Hay una condición de salida o caso base: cuando n == 0. Pero el valor de n nunca coincide con el caso base.

Para solucionar esto podemos usar la función isinstance() para determinar si el tipo del parámetro es entero y también
controlar que el parámetro sea positivo:
def factorial(n):
if not isinstance(n, int):
print('La función factorial solo se aplica a enteros.')
return None
elif n < 0:
print('La función factorial solo se aplica a enteros positivos.')
return None
elif n == 0:
return 1
else:
return n * factorial(n-1)

ESPACIOS DE NOMBRES Y ALCANCE DE VARIABLES

Un nombre de variable puede referirse a diferentes cosas, dependiendo de dónde se use.

Los programas de Python tienen varios espacios de nombres. Un espacio de nombres es una sección dentro de la cual
un nombre en particular es único y no está relacionado con el mismo nombre en otros espacios de nombres.

Cada función define su propio espacio de nombres. Si define una variable con nombre x en un programa principal y
otra variable llamada x en una función, se refieren a cosas diferentes. Sin embargo, en caso de ser necesario, esto
puede superarse. Se puede acceder a variables en otros espacios de nombres de varias maneras.

La parte principal de un programa define el espacio de nombres global; por lo tanto, las variables en ese espacio de
nombres son variables globales.

Puede obtenerse el valor de una variable global desde dentro de una función:
animal = 'carpincho'
def print_en_funcion():
print('En función:', animal)
...
print('En el nivel superior:', animal) → En el nivel superior: carpincho
print_en_funcion() → En función: carpincho

Cambiamos un poco el ejemplo:


animal = 'carpincho'
def cambiar_local():
animal = 'benteveo'
print('En función cambiar_local():', animal, id(animal))
print('En el nivel superior:', animal, id(animal))
→ En el nivel superior: carpincho 2204778549872
cambiar_local() → En función cambiar_local(): benteveo 2204778550064

¿Qué pasó aquí? La primera línea asignó la cadena 'carpincho' a una variable global llamada animal.

La función cambiar_local() también tiene una variable llamada animal, pero está en su espacio de nombres local.

Usamos la función id() para imprimir el valor único de cada objeto y probar que la variable animal dentro de
cambiar_local() no es lo mismo que animal en el nivel principal del programa.

Para acceder a la variable global en lugar de la local dentro de una función, debe ser explícito y usar la palabra clave
global:
animal = 'carpincho'
def cambiar_local():
global animal
animal = 'benteveo'
print('En función cambiar_local():', animal, id(animal))
print('En el nivel superior:', animal, id(animal))
→ En el nivel superior: benteveo 2492781351408
cambiar_local() → En función cambiar_local(): benteveo 2492781351408

Si no anteponemos global al nombre de la variable dentro de una función, Python usa el espacio de nombres local y
la variable es local. Desaparece después de que se completa la función.

UNIDAD VI: COLECCIONES Y TIPOS DE DATOS COMPUESTOS


TIPOS DE DATOS COMPUESTOS

Algunos de los tipos de datos que hemos visto hasta el momento son: bool, int, float, y string.

Los strings son muy diferentes del resto porque están hechos de piezas menores: caracteres.

Los tipos que comprenden piezas menores se llaman tipos de datos compuestos.
Dependiendo de lo que necesitemos hacer, podemos tratar un tipo compuesto como una única cosa o acceder sus
partes componentes.

Los tipos de datos compuestos de Python que trataremos en esta asignatura son:

• Listas
• Tuplas
• Diccionarios

LISTAS – DEFINICIÓN

Una lista es un conjunto ordenado de valores, en el cual cada valor se puede identificar por un índice.

Las listas en Python son uno de los tipos o estructuras de datos más versátiles del lenguaje, ya que permiten almacenar
un conjunto arbitrario de datos. Es decir, podemos guardar en ellas prácticamente lo que sea.

Los valores que constituyen una lista se llaman elementos.

Las listas son similares a los strings, que son conjuntos ordenados
de caracteres, excepto en que los elementos de una lista pueden
ser de cualquier tipo.

Las listas y los strings, (entre otros tipos) que se comportan como
conjuntos ordenados, se denominan secuencias.

VALORES DE UNA LISTA

Hay varias maneras de crear una nueva lista; la más sencilla es encerrar sus elementos entre corchetes:

[10, 20, 30, 40]


["spam", "elástico", "golondrina"]

Los elementos de una lista pueden ser de distinto tipo:


["hola", 2.0, 5, [10, 20]]

Se dice que una lista dentro de otra lista está anidada.

Hay una lista especial que no contiene elementos. Se llama lista vacía y se representa así: []

Anteriormente ya creamos listas! ¿Se acuerdan de print(list(range(4))?

• Allí temporalmente convertimos un rango en una lista para poder imprimirlo.

También podemos crear una lista a partir de un string: list("Python")

ACCESO A ELEMENTOS

Podemos asignar listas a variables o pasar listas como parámetros a funciones:

» beatles = ["John", "Paul", "George", "Ringo"]


» numeros = [17, 123]
» vacio = []
» print(beatles, numeros, vacio)
→ ['John', 'Paul', 'George', 'Ringo'] [17, 123] []

La sintaxis para acceder a los elementos de una lista es la misma que para acceder a los caracteres de un string: el
operador corchetes []. La expresión dentro de los corchetes especifica el índice.

Recordar que los índices siempre comienzan en cero:


» print(beatles[0]) → ‘John’
» numeros[1] = 5

El operador [] puede aparecer en cualquier parte de una expresión. Cuando aparece a la izquierda de una asignación,
cambia uno de los elementos de la lista, de manera que el “unésimo" elemento de numeros, que era 123, ahora es 5.

Se puede usar como índice cualquier expresión entera.

Si intenta acceder (leer o modificar) un elemento que no existe, obtendrá un error en tiempo de ejecución:

» numeros[2] = 5
IndexError: list assignment index out of range

Si especificamos un índice negativo, se cuenta hacia atrás desde el final de la lista.

» numeros[-1] → 5
» numeros[-2] → 17
» numeros[-3]

RECORRIDOS

La función len() toma una lista y devuelve su tamaño. Es buena idea usar este valor como límite superior a la hora de
recorrer un bucle en lugar de usar constantes literales.

Es muy habitual usar una variable de bucle como índice para una lista:

tortugas = ["Leonardo", "Raphael", "Donatello", "Miguel Ángel"]


i = 0
while i < len(tortugas):
print(tortugas[i])
i = i + 1

Este bucle while cuenta desde 0 hasta la longitud de la lista (en este caso 4). Cuando la variable de bucle vale 4, la
condición falla y acaba el bucle.

Por tanto, el cuerpo del bucle sólo se ejecuta cuando i es 0, 1, 2 y 3.

Cada vez que recorremos el bucle, la variable i se usa como índice de la lista, imprimiendo el elemento í-esimo. Esta
plantilla de computación se llama recorrido de lista

PERTENENCIA

in es un operador booleano que comprueba la pertenencia a una secuencia.

Lo usamos cuando vimos el bucle for para rangos y strings, pero también funciona con las listas y otras secuencias:

» tortugas = ["Leonardo", "Raphael", "Donatello", "Miguel Ángel"]


» "Leonardo" in tortugas
True
» "Rocoso" in tortugas
False

Como “Leonardo” es un miembro de la lista tortugas, el operador in devuelve True (verdadero). Como “Rocoso” no
está en la lista tortugas, in devuelve False (falso).
Podemos usar not en combinación con in para comprobar si un elemento no es miembro de una lista:

» "Bebop" not in tortugas


True

LISTAS Y BUCLES FOR

Los bucles for también funcionan con listas. Comparamos los bucles para el ejemplo anterior:
for tortuga in tortugas: i = 0
print(tortuga) while i < len(tortugas):
print(tortugas[i])
i = i + 1

El bucle for es más conciso porque podemos eliminar i (la variable de bucle) y también su actualización.

Más aún, casi se lee igual que en español, “Para (cada) tortuga en (la lista de) tortugas, imprime el nombre de la
tortuga”.

Otros ejemplos:

for fruta in [”ananá”, “banana”, “manzana”]:


print(“Me gusta comer” + fruta + “s!”)

OPERACIONES CON LISTAS

El operador + concatena listas:


» a = [1, 2, 3]
» b = [4, 5, 6]
» c = a + b
» print(c) → [1, 2, 3, 4, 5, 6]

De forma similar, el operador * repite una lista un número dado de veces:

» [0] * 4 → [0, 0, 0, 0]
» [1, 2, 3] * 3 → [1, 2, 3, 1, 2, 3, 1, 2, 3]

En el primer ejemplo la lista [0] contiene un solo elemento que es repetido cuatro veces. En el segundo ejemplo, la
lista [1, 2, 3] se repite tres veces.

SLICES

Las operaciones de slices que vimos para strings también funcionan sobre listas:

» lista = [’a’, ’b’, ’c’, ’d’, ’e’, ’f’]


» lista[1:3] → [’b’, ’c’]
» lista[:4] → [’a’, ’b’, ’c’, ’d’]
» lista[3:] → [’d’, ’e’, ’f’]
» lista[:] → [’a’, ’b’, ’c’, ’d’, ’e’, ’f’]
MUTABLE VS INMUTABLE

La mutabilidad define si un dato puede ser mutado (cambiado) tras ser inicializado o siempre mantiene el mismo valor,
tanto para la variable original como para las demás referencias que tenga el valor.

• Este aspecto es muy importante a la hora de trabajar con listas e intentar cambiar sus valores en cualquier
parte del programa para evitar al máximo la aparición de efectos colaterales al actualizar una variable que se
espera que no se actualice.

Los diferentes tipos de Python, pueden ser clasificados atendiendo a su mutabilidad. Pueden ser:

• Inmutables: Si no permiten ser modificados una vez creados (Booleanos, Complejos, Enteros, Float, Frozenset,
Strings, Tuplas, Range y Bytes).
• Mutables: Si permiten ser modificados una vez creados (Listas, Sets, Bytearray, Memoryview, Diccionarios).

LISTAS - TIPOS DE DATOS MUTABLES

A diferencia de los strings, las listas son mutables, lo que significa que podemos cambiar sus elementos. Podemos
modificar uno de sus elementos usando el operador corchetes en el lado izquierdo de una asignación:
» frutas = ["ananá", "banana", "manzana"]
» frutas[0] = "pera"
» frutas[-1] = "naranja"
» print(frutas) → [’pera’, ’banana’, ’naranja’]

Con el operador de slice podemos reemplazar varios elementos a la vez:

» lista = [’a’, ’b’, ’c’, ’d’, ’e’, ’f’]


» lista[1:3] = [’x’, ’y’]
» print(lista) → [’a’, ’x’, ’y’, ’d’, ’e’, ’f’]

Además, puede eliminar elementos de una lista asignándoles la lista vacía:


» lista = [’a’, ’b’, ’c’, ’d’, ’e’, ’f’]
» lista[1:3] = []
» lista → [’a’, ’d’, ’e’, ’f’]

BORRADO DE UNA LISTA

El uso de slices para borrar elementos de una lista puede ser confuso y propicio a errores. Python nos da una alternativa
que resulta más legible: del que elimina un elemento de una lista:

a = [’uno’, ’dos’, ’tres’]


del a[1]
print(a) → [’uno’, ’tres’]

del maneja índices negativos y provoca un error en tiempo de ejecución sin el índice está fuera de límites.

Puede usarse un slice como índice para del:

lista = [’a’, ’b’, ’c’, ’d’, ’e’, ’f’]


del lista[1:5]
print(lista) → [’a’, ’f’]
MÉTODOS DE LISTAS

Python nos provee de métodos que operan con las listas. Por ejemplo, append agrega un nuevo elemento al final de
la lista:

» t = ['a', 'b', 'c']


» t.append('d')
» print(t) → ['a', 'b', 'c', 'd']

El método extend toma una lista como argumento y agrega todos sus elementos:

» t1 = ['a', 'b', 'c']


» t2 = ['d', 'e']
» t1.extend(t2)
» print(t1) → ['a', 'b', 'c', 'd', 'e']

El método sort ordena todos los elementos de la lista de mayor a menor:

» t3 = ['d', 'c', 'e', 'b', 'a']


» t3.sort()
» print(t3) → ['a', 'b', 'c', 'd', 'e']

Otros métodos:

• insert(): agrega un elemento en la posición especificada por el índice.


• remove(): quita un elemento a partir del valor especificado.
• pop(): quita un elemento a partir del índice especificado.
• index(): devuelve el índice del elemento pasado por parámetro.
• clear(): vacía la lista.
• reverse(): invertir el orden de los elementos en la lista.

LISTAS COMO PARÁMETROS

Cuando se pasa una lista como argumento, en realidad se pasa una referencia a ella, no una copia de la lista. Por
ejemplo, la función cabeza() toma una lista como parámetro y devuelve el primer elemento.
def cabeza(lista):
return lista[0]

Así es como se usa.

numeros = [1,2,3]
cabeza(numeros) → 1

El parámetro lista y la variable numeros son alias de un mismo objeto. Si la función modifica una lista pasada como
parámetro, el que hizo la llamada verá a el cambio. borra_cabeza() elimina el primer elemento de una lista.

def borra_cabeza(lista):
del lista[0]

Aquí vemos el uso de borra_cabeza():


numeros = [1,2,3]
borra_cabeza(numeros)
print(numeros) → [2, 3]

LISTAS ANIDADAS

Una lista anidada es una lista que aparece como elemento dentro de otra lista.

En esta lista, el tercer elemento es una lista anidada:

» lista = ["hola", 2.0, 5, [10, 20]]

Si imprimimos lista[3], obtendremos [10, 20]. Para extraer los elementos de la lista anidada, podemos proceder en dos
pasos:

» elt = lista[3]
» elt[0] → 10

O podemos combinarlos:

» lista[3][1] → 20

Los operadores corchete se evalúan de izquierda a derecha, así que esta expresión saca el tercer elemento de lista y
luego extrae el primer elemento de ella.

MATRICES

Es común usar listas anidadas para representar matrices. Por ejemplo, la matriz:

» matriz = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

matriz es una lista con tres elementos, siendo cada elemento una fila de la matriz. Podemos elegir una fila entera de
la matriz de la forma normal:
» matriz[1] → [4, 5, 6]

O tomar sólo un elemento de la matriz usando la forma de doble índice:

» matriz[1][1] → 5

El primer índice escoge la fila y el segundo la columna. Aunque esta manera de representar matrices es común no es
la única posibilidad. Una pequeña variación consiste en usar una lista de columnas en lugar de filas.

CADENAS Y LISTAS

Dos de las funciones más útiles de los strings tienen que ver con listas de cadenas. La función split() divide una cadena
en una lista de palabras.

Por defecto, cualquier número de caracteres de espacio en blanco se considera un límite de palabra:

» cancion = "La lluvia en Sevilla..."


» cancion.split() → [’La’, ’lluvia’, ’en’, ’Sevilla…’]

Se puede usar un argumento opcional llamado delimitador para especificar qué caracteres se usarán como límites de
palabra. El siguiente ejemplo usa la cadena “l” como delimitador:

» cancion = "La lluvia en Sevilla..."


» cancion.split(“l”) → [’La ’, ’uvia en Sevi’, ’a...’]

Observe que el delimitador no aparece en la lista

La función join() es la inversa de split(). A partir de un string, toma una lista de cadenas y concatena los elementos con
el primer string como separador:
» lista = [’La’, ’lluvia’, ’en’, ’Sevilla...’]
» ‘’.join(lista) → ’LalluviaenSevilla...’

En el ejemplo anterior usamos el string vacío como delimitador, por eso el resultado. Si usamos “_” como separador,
el efecto es:

» ‘_’.join(lista) → ’La_lluvia_en_Sevilla...’

TUPLAS

Al igual que las listas, las tuplas son una secuencia de valores de cualquier tipo que están indexadas por enteros. La
diferencia principal entre una tupla y una lista es que las tuplas son inmutables.

Sintácticamente una tupla es una lista de valores separados por comas:

» t = ‘a’, ‘b’, ‘c’, ‘d’, ‘e’

Sin embargo, aunque no es necesario, es común ver las tuplas encerradas entre paréntesis:

» t = (‘a’, ‘b’, ‘c’, ‘d’, ‘e’)

Para crear una tupla con un único elemento, tenemos que incluir la coma al final:

» t1 = ‘a’,
» type(t1) → <class ‘tuple’>

Sin la coma final se trata de un string.

Otra forma de crea una tupla es utilizando la función tuple(). Sin argumentos, creamos una tupla vacía:
» t = tuple()
» t () →

Si pasamos por parámetro a la función tuple() una secuencia (string, lista o tupla), el resultado es una tupla con los
elementos de la secuencia.

» t = tuple(‘Independiente’)
» t → ('I', 'n', 'd', 'e', 'p', 'e', 'n', 'd', 'i', 'e', 'n', 't', 'e')

TUPLAS – OPERADORES

La mayoría de los operadores que funcionan con listas también lo hacen para las tuplas.

El operador corchetes indexa un elemento:

» t = (‘a’, ‘b’, ‘c’, ‘d’, ‘e’)


» t[0] → ‘a’

Y el operador slice selecciona un rango de elementos:

» t[1:3] → (‘b’, ‘c’)

Pero si intentamos modificar uno de los elementos de la tupla tendremos un error:


» t[0] = ‘A’ → TypeError: object doesn’t support item assigment

Dado que las tuplas son inmutables, no podemos modificar los elementos. Pero podemos reemplazar una tupla con
otra

» t = (‘A’, ) + t[1:]
» t → (‘A’, ‘b’, ‘c’, ‘d’, ‘e’)
Esto crea una nueva tupla y luego copia el resultado en t.

ASIGNACIÓN

Cuando hicimos nuestros primeros ejercicios con Python vimos tuplas! El intercambio de valores que hacíamos con
variables temporales:

» temp = a
» a = b
» b = temp

Con tuplas, la solución es más elegante: a, b = b, a

El lado izquierdo es una tupla de variables y el lado derecho es una expresión que devuelve una tupla. Cada valor es
asignado a su respectiva variable. Todas las expresiones del lado derecho son evaluadas antes de la asignación.

El número de variables del lado izquierdo y del lado derecho tienen que ser exactamente el mismo.

De manera más general podemos decir que del lado derecho podemos tener cualquier tipo de secuencia (string, lista
o tupla). Por ejemplo, para dividir una dirección de email entre nombre de usuario y dominio podemos escribir:

» direccion = ‘inovello@uner.edu.ar’
usuario, dominio = direccion.split(‘@’)

TUPLAS Y VALORES DE RETORNO

En términos estrictos una función puede solo retornar un valor, pero si el valor es una tupla, el efecto es el mismo que
retornar múltiples valores.

Por ejemplo, si queremos dividir dos enteros y computar el coeficiente y el resto, es ineficiente computar x // y y luego
x % y. Es una mejor solución computar ambos al mismo tiempo.

Python cuenta con la función integrada divmod() que toma dos argumentos y nos retorna una tupla con dos valores:
el cociente y el resto.

Podemos almacenar el resultado en una tupla:

» t = divmod(7,3)
» t (2, 1) →

O utilizar la asignación de tupla para almacenar valores de manera separada:

» cociente, resto = divmod(7, 3)


» cociente 2 →
» resto 1

MÉTODOS DE TUPLAS

Como son inmutables, las tuplas no cuentan con ningún método que permita modificar los elementos que contienen.
A continuación los métodos de tuplas:

• count(): cuenta el número de veces que un valor pasado por parámetro se ha encontrado en la tupla.
• index(): busca el valor que se ha pasado por parámetro y devuelve el índice en el que se ha encontrado.

DICCIONARIOS

Los tipos compuestos que hemos visto hasta ahora (cadenas, listas y tuplas) usan enteros como índices.

• Si intenta usar cualquier otro tipo como índice provocaría un error.


Un diccionario contiene una colección de índices, que se llaman claves, y una colección de valores.

• Cada clave está asociada a un único valor. La asociación entre una clave y un valor recibe el nombre de par
clave-valor, ítem o entrada.

Los diccionarios son similares a otros tipos compuestos excepto en que pueden usar como índice cualquier tipo
inmutable.

• Sirven para la construcción de muchos elegantes y eficientes algoritmos.

En términos matemáticos un diccionario representa un mapeo desde claves a valores. De forma que para cada clave
hay un valor.

• Como ejemplo, vamos a construir un diccionario que haga un mapeo de palabras del español al inglés.

Una forma de crear un diccionario es empezar con el diccionario vacío y añadir elementos.

• El diccionario vacío se expresa usando llaves {} ó utilizando la función dict().

» diccionario = {}

Para agregar ítems en el diccionario utilizamos corchetes:


» diccionario[‘uno’] = ‘one’

La línea anterior crea un ítem que mapea la clave ‘uno’ al valor ‘one’. Si nuevamente imprimimos el diccionario vemos
el par clave-valor con el símbolo : (dos puntos) entre la clave y el valor.

{‘uno’: ‘one’}

El formato de salida de un diccionario es también formato de entrada. Podemos crear un diccionario con tres entradas:

» diccionario = {‘uno’: ‘one’, ‘dos’: ‘two’, ‘tres’: ‘three’}

A la hora de imprimir por pantalla diccionario puede suceder que las claves no estén en el orden en que las insertamos.
Esto no es un problema porque para acceder a los valores de un diccionario siempre usamos una clave como índice.

» diccionario[‘dos’] → ‘two’

Si la clave no está en el diccionario vamos a tener una excepción:


» diccionario2[‘cuatro’] → KeyError: 'cuatro'

La función len() que vimos para strings, listas y tuplas tiene la misma semántica con diccionarios devolviéndonos la
cantidad de pares clave-valor que hay en el diccionario.

» len(diccionario2) 3 →

El operador in también funciona con los diccionarios, nos indica si hay alguna entrada con clave igual a la que estamos
buscando.

» ‘uno’ in diccionario → True


» ‘cinco’ in diccionario → False

Si necesitamos controlar si hay algún valor en el diccionario podemos utilizar el método values() en combinación con
el operador in:

‘one’ in diccionario.values() → True


‘five’ in diccionario.values() → False

Utilizando del podemos quitar una entrada el diccionario:

» del diccionario[‘uno’] { → ‘dos’: ‘two’, ‘tres’: ‘three’}


DICCIONARIOS PARA REPRESENTAR ENTIDADEDS CON VARIAS PROPIEDADES

En Python podemos utilizar los diccionarios para


establecer las propiedades y valores con los que cuenta
una entidad. Por ejemplo:

» vehículo = {
‘tipo’: ‘Automóvil’,
‘año’: 2022,
‘marca’: ‘Ford’,
‘modelo’: ‘Focus ST’,
‘color’: ‘Azul’}

Podemos visualizarlo también de forma tabular:

DICCIONARIOS COMO COLECCIÓN DE CONTADORES

Supongamos que dado un string queremos contar cuántas veces aparece cada letra en él. Hay varias soluciones
posibles:

1) Podemos crear 26 variables, una para cada letra del alfabeto. Luego, podemos recorrer el string y para cada
carácter incrementar el contador de la variable correspondiente usando condicionales anidados.
2) Una segunda alternativa es crear una lista con 26 elementos y luego convertir cada carácter a número
(utilizando la función integrada ord()), usando el número como índice dentro de la lista y el incremento del
contador apropiado.
3) Podemos crear un diccionario con caracteres como claves y contadores como los valores correspondientes. La
primera vez que nos encontramos con un carácter, tendremos que agregar un ítem al diccionario. Las próximas
ocurrencias, bastaría con incrementar el valor de un ítem existente.

Cada una de estas opciones, si bien lleva a cabo la misma computación, cada una de ellas la implementa de manera
diferente.

Una implementación es una forma de llevar a cabo una computación; algunas implementaciones son mejores que
otras. Por ejemplo, la ventaja de la implementación que utiliza un diccionario es que no tenemos que conocer de
antemano qué letras van a aparecer en el string y sólo guardaremos en el diccionario las letras que aparecen
(ahorrando memoria).

BUCLES Y DICCIONARIOS

Si usamos un diccionario en un bucle for, haremos un recorrido por las claves de ese diccionario. Por ejemplo, d_print()
imprime cada clave y su correspondiente valor.

def d_print(dict):
for c in dict:
print(c, dict[c])
» d_print(histograma(‘Lara’))

Las claves no tienen un orden particular. Para recorrer las claves en orden tenemos que usar la función integrada
sorted():

def d_print_sorted(dict):
for key in sorted(dict):
print(key, dict[key])
» d_print_sorted(histograma(‘Lara’))

DICCIONARIOS Y LISTAS

Las listas pueden aparecer como valores de un diccionario.

Dado un diccionario que mapea letras y su frecuencia, es posible que necesitemos invertir el diccionario. Es decir,
crear un diccionario que haga un mapeo de frecuencias a letras.

• Como podemos tener muchas letras con la misma frecuencia, cada valor en el diccionario invertido deberá
ser una lista de letras.

MÉTODOS DE DICCIONARIOS

• clear(): elimina todo el contenido del diccionario.


• get(): nos permite consultar el valor para una clave determinada. El segundo parámetro es opcional, y en el
caso de proporcionarlo es el valor a devolver si no se encuentra la clave.
• items(): devuelve una lista con las entradas del diccionario. Si se convierte en una lista se puede indexar como
si de una lista normal se tratase, siendo los primeros elementos serán las claves y los segundos los valores.
• keys(): retorna una lista con todas las claves del diccionario.
• values(): devuelve una lista con todos los valores del diccionario.
• pop(): elimina la clave que se pasa como parámetro y devuelve su valor asociado. Daría un error si se intenta
eliminar una clave que no existe.
• popitem(): elimina de manera aleatoria un elemento del diccionario.
• update(): se llama sobre un diccionario y tiene como argumento otro diccionario. Los valores son actualizados
y si alguna clave del nuevo diccionario no está, es añadida.

UNIDAD VII – ENTRADA Y SALIDA


INTERFACES DE LÍNEA DE COMANDOS (CLI)

Las Command Line Interface o interfaces de línea de comandos (comúnmente abreviado como CLI) son una
herramienta que ofrecen gran cantidad de programas para interactuar con ellos.

En Windows, el comando dir permite listar las carpetas o directorios y archivos. Por ejemplo, dir /o:d:

• o: muestra los elementos ordenados según lo indicado por el parámetro que sigue.
• :d implica mostrar los elementos ordenados por fecha de modificación.

En Linux, el comando ls tiene el mismo propósito. Por ejemplo, ls -ta:

• t: muestra los elementos ordenados según fecha de modificación.


• a: muestra los archivos ocultos.

En ambos sistemas operativos con mkdir creamos una carpeta o directorio. Por ejemplo, mkdir prog1

En los ejemplos podemos identificar varias partes:

• Por un lado tenemos el comando que determinar qué programa se va a ejecutar: dir, ls o mkdir.
• Luego tenemos las opciones como -ta o -p, que modifican el comportamiento del comando que precede. Por
ejemplo, la opción -t ordena los ficheros por orden de modificación.
• Por último tenemos los argumentos que se le pasan al comando. Pueden no existir como en el caso de ls, o
tener uno como en el caso de mkdir, que indica el nombre del fichero a crear.

CLI EN PYTHON

En ocasiones puede ser necesario que por las características del problema, debamos construir un programa sin interfaz
gráfica de usuario pero que acepte parámetros y que en función de ellos el comportamiento del programa cambie.

Supongamos que tenemos un programa que implementa una calculadora que queremos que por consola de comandos
se ejecute así:

python calculadora sumar 5 2

Para procesar los argumentos (en el ejemplo anterior 5 y 2) podemos utilizar el módulo sys.

import sys
print(sys.argv)

La llamada a sys.argv captura todo lo que se pasa después de python y lo deja en una lista:

• El primer elemento argv[0] nos devuelve el nombre del script.


• Y a continuación cada uno de los elementos de la lista tienen un argumento.

REPRESENTACIÓN INTERNA DE DATOS

En unidades anteriores hablamos que las computadoras manejan dos estados de tensión: encendido y apagado.

Esos estados de tensión pueden relacionarse con el sistema binario y por ende, de manera natural, a la representación
interna de la información.

De alguna forma se tienen que traducir los 0s y 1s con los que trabajan las computadoras a un conjunto de caracteres.

Estas transformaciones se denominan tablas de códigos de entrada/salida (E/S) o sistema de codificación de


caracteres (charset encoding)

Existen codificaciones normalizadas y estandarizadas que son utilizadas por los fabricantes de computadoras.

ASCII

Es el acrónimo de American Standard Code for Information


Interchange, es un código de caracteres basado en el alfabeto
latino, tal como se usa en inglés. Fue creado por ANSI en 1963.

Usa 7 bits, por ende se pueden representar 27 = 128


caracteres.

Ejemplo: PROG1 en ASCII es:

La limitación del ASCII es la ausencia de caracteres


ortográficos de otros idiomas.

UNICODE

Surge para solucionar los problemas del ASCII:

• Imposibilidad de representar caracteres de múltiples idiomas.


• Combinar textos de varios idiomas.
Es mantenido por el Unicode Technical Committee (UTC).

Unicode proporciona un número entero único (punto de código) para cada carácter, sin importar la plataforma, sin
importar el programa ni el idioma.

Fue originalmente definido en 1996 como un conjunto de caracteres de 16 bits. Sin embargo, no fueron suficientes,
principalmente cuando se decidió el enfoque de codificar los ideografos Han (chinos).

Las formas de codificación de Unicode reglamentan la forma en que los puntos de código se transformarán en unidades
tratables por el medio digital.

Unicode define tres formas de codificación o UTFs (Formatos de Transformación Unicode - Unicode Transformation
Format): UTF-8, UTF-16 y UTF-32

• UTF-8: usa 8 bits por unidad de código. Cada carácter es representado con 1 a 4 unidades de código. Por eso
se dice que son códigos de longitud variable.
o “A”, U+0041, utf-8 = 0x41
o “º”, U+00ba, utf-8 = 0xc2 0xba
o “ ”⋇ , U+22c7, utf-8 = 0xe2 0x8b 0x87
• UTF-16: usa unidad de código de 16 bits. Cada carácter es representado con 1 ó 2 unidades.
• UTF-32: usa 1 unidad de código de 32 bits. Son representaciones de longitud fija.

PERSISTENCIA

Todos los programas que hicimos hasta al momento fueron transitorios o temporales en el sentido que se ejecutan
por un período de tiempo muestran sus salidas por pantalla pero cuando terminan los datos desaparecen.

• Si ejecutamos el programa nuevamente, inician en un estado limpio.

Otros programas son persistentes:

• Se ejecutan por un período de tiempo largo (o todo el tiempo).


• Guardan toda o parcialmente la información que manejan en almacenamiento permanente. Por ejemplo:
disco rígido.
• Si se reinician, continúan donde habían quedado.

Ejemplos de programas persistentes son:

• Sistemas operativos: se ejecutan siempre que la PC está encendida.


• Servidores Web: se ejecutan todo el tiempo esperando solicitudes.

Una de las formas más fáciles para que los programas mantengan información es leer y escribir archivos de texto.

ARCHIVOS Y DIRECTORIOS

Un archivo es una secuencia de bytes, almacenados en un sistema de archivos que puede ser accedido por su nombre.
Un directorio es una colección de archivos y posiblemente otros directorios. El término carpeta es sinónimo de
directorio.

• Tal y como las palabras pueden escribirse en un papel los datos pueden escribirse en un archivo de
computadora.

Los archivos se diseñan para diferentes propósitos. Puede estar diseñado para almacenar una imagen, un mensaje
escrito, un video o un programa de computadora o cualquier otro tipo de información.

En algunos sistemas operativos la extensión del archivo establece reglas de cómo los bytes que componen el archivo
deben ser organizados e interpretados para que tengan sentido.

• Por ejemplo, en un archivo con extensión txt, los bytes de un archivo de texto plano están asociados con la
tabla de caracteres ASCII o UTF-8.

ENTRADA Y SALIDA DE ARCHIVOS

En Python es posible abrir archivos, leer su contenido y escribir nuevo contenido en ellos.

• Podemos procesar archivos de texto así como también archivos de contenido binario.
• Para simplificar, nos centraremos en leer y escribir archivos de texto (también llamados de texto plano).

Con Python podemos fácilmente leer desde un archivo a la memoria de la PC y escribir desde la memoria de la PC a
un archivo.

CREAR O ABRIR ARCHIVOS CON OPEN()

Es necesario invocar a la función open() antes de hacer lo siguiente:

• Leer un archivo existente.


• Escribir en un nuevo archivo.
• Agregar al final de un archivo existente.
• Sobrescribir un archivo existente.

» obj_archivo = open(nombre_archivo, modo)

Las partes que componen la instrucción anterior son:

• obj_archivo: es el objeto archivo devuelto por la función open()


• nombre_archivo: es un string con el nombre del archivo.
• modo: es un string indicando el tipo del archivo y lo que queremos hacer con él.

La primera letra del modo indica la operación:

• r: significa lectura.
• w: significa escritura. Si el archivo no existe, entonces es creado. Si existe es sobrescrito.
• x: escribe solo si el archivo no existe previamente.
• a: significa agregar. Es decir, escribir al final si ya existe.

La segunda letra de modo es el tipo del archivo:

• t: (o nada) significa texto.


• b: significa binario.

Luego de abrir un archivo, podemos invocar a las funciones para leer o escribir datos.

Por último, es necesario cerrar el archivo para asegurarnos que las escrituras sean completadas y que la memoria sea
liberada.

• Más tarde, veremos cómo usar la palabra reservada with para automatizar esta tarea.

Este programa abre un archivo que se llama prog1.txt y lo cierra sin hacer nada.
Esto crearía un archivo vacío:

» obj_archivo = open(‘prog1.txt’, ‘wt’)


» obj_archivo.close()

ESCRIBIR ARCHIVOS DE TEXTO

Escribir un archivo de texto con print():

• Vamos a re-crear prog1.txt pero ahora vamos a escribir una línea en él y luego cerrarlo.

» obj_archivo = open('prog1.txt', 'wt')


» print('Vamooo!!! Cree un archivo', file=obj_archivo)
» obj_archivo.close()

• Al igual que lo hicimos anteriormente, se crea un nuevo archivo prog1.txt vacío. Si ya existía, lo sobrescribimos.
• Usamos el argumento file en la función print(). Sin él print() escribiría en la salida estándar, que es la terminal.

Escribir un archivo de texto con write():

• Para escribir una línea en un archivo también podemos usar el método write().
• Las diferencias principales entre print() y write() son:
o El método write() nos devuelve el número de bytes escritos. La función print() no.
o El método write() no agrega espacios en blanco o caracteres de salto de línea, mientras que print() sí
lo hace.

Si tenemos un string muy largo podemos escribirlo por partes utilizando slices:

obj_archivo = open('jugadores-chelsea.txt', 'wt', encoding='utf-8')


longitud = len(cadena)
desplazamiento = 0
tamanio_parte = 100
while True:
if desplazamiento > longitud:
break
obj_archivo.write(cadena[desplazamiento:desplazamiento+tamanio_parte])
desplazamiento += 100
obj_archivo.close()

LEER UN ARCHIVO DE TEXTO CON READ(), READLINE() O READLINES()

Se puede invocar al método read() sin argumentos para tomar todo el contenido del archivo de una sola vez. Sin
embargo, hay que tener cuidado si hacemos esto con archivos grandes: Un archivo de un gigabyte consumirá esa
cantidad de memoria:

obj_archivo = open('jugadores-liverpool.txt', 'rt', encoding='utf-8')


cadena = obj_archivo.read()
obj_archivo.close()
print("longitud:", len(cadena)) → 157
Podemos proveer un máximo de caracteres para establecer cuánto queremos leer en una sola operación. Si queremos
leer 100 caracteres a la vez hacemos lo siguiente:
cadena = ''
obj_archivo = open('jugadores-liverpool.txt', 'rt', encoding='utf-8')
tamanio_parte = 100
while True:
fragmento = obj_archivo.read(tamanio_parte)
if not fragmento:
break
cadena += fragmento
obj_archivo.close()
print("longitud:", len(cadena)) → 157

Otra opción es leer un archivo línea por línea utilizando la función readline(). En este ejemplo agregamos cada línea al
final del string cadena para reconstuir el string original:
cadena = ''
obj_archivo = open('jugadores-liverpool.txt', 'rt', encoding='utf-8')
while True:
linea = obj_archivo.readline()
if not linea:
break
cadena += linea
obj_archivo.close()
print('longitud:', len(cadena)) → 157

Cuando todo el archivo es leído readline() al igual que read(), retorna un string vacío que es evaluado como False.

La forma más fácil de leer un archivo valiéndonos de que el objeto archivo soporta operaciones de iteración. Esto
retorna una línea a la vez, similar al ejemplo anterior pero con menos código:

cadena = ''
obj_archivo = open('jugadores-liverpool.txt', 'rt', encoding='utf-8')
for linea in obj_archivo:
cadena += linea
obj_archivo.close()
print('longitud:', len(cadena)) → 157

Todos los ejemplos precedentes arman un único string. La función readlines() lee todas las líneas de una sola vez y
retorna una lista de strings donde cada elemento es una línea del archivo.

obj_archivo = open('jugadores.txt', 'rt', encoding='utf-8')


lineas = obj_archivo.readlines()
obj_archivo.close()
print (len(lineas), 'líneas leídas') → 5 lineas leídas
for linea in lineas:
print(linea, end='')

CIERRE AUTOMÁTICO DE ARCHIVOS CON WITH

Si nos olvidamos de cerrar un archivo que hemos abierto, será cerrado por Python cuando no exista ninguna referencia
a la variable.

Esto significa que si abrimos un archivo dentro de una función y no lo cerramos explícitamente, será cerrado
automáticamente cuando la función termine.

Pero puede ser que hayamos abierto el archivo en una función que está mucho tiempo ejecutándose o en la sección
principal de nuestro programa. El archivo debería ser cerrado para forzar que todas las escrituras pendientes se
completen.

Podemos usar la palabra reservada with expresión as variable:


with open('jugadores-liverpool.txt', 'wt', encoding='utf-8') as archivo_salida:
archivo_salida.write(cadena)

Después que el bloque de código (en este caso una sola línea) es completado el archivo es cerrado automáticamente.

OPERACIONES CON ARCHIVOS

Al igual que muchos lenguajes, la mayoría de las operaciones de archivos con Python, son heredadas de los sistemas
de archivos Unix.

Las tareas de este tipo son llevadas a cabo utilizando o bien funciones del módulo os.path o con el módulo pathlib.

exists(): verifica si un archivo o directorio existe. os.path.exists(‘prog1.txt’)

isfile(): controla si el nombre se refiere a un archivo, un directorio o un enlace simbólico.

isdir(): determina si el nombre pasado por parámetro corresponde a un directorio o carpeta.

También tenemos opciones para:

• Copiar, renombrar y eliminar archivos.


• Cambiar permisos.
• Cambiar propiedad.
• Listar, crear y eliminar directorios.
• Cambiar de directorio (cd).

RUTAS

Casi todas las computadoras utilizan un sistema de archivos jerárquico, donde los directorios
contienen o archivos u otros directorios, en varios niveles.

Cuando necesitamos referirnos a un archivo o directorio específico necesitamos su ruta. Es


decir, la secuencia de directorios necesarios para llegar al archivo.

Esto puede ser absoluto desde la raíz del sistema de archivos o relativo a un directorio actual.

Tenemos que tener en cuenta que las PCs con sistemas operativos Linux y Mac utilizan la barra
o slash ‘/’ para separar directorios mientras que las PCs con sistemas operativos Windows
utilizan la barra invertida o backslash ‘\’.
Cuando trabajamos con Python en sistemas Windows podemos usar backslash pero tenemos que tener en cuenta que
ese carácter es también utilizado para definir secuencias de escape así que para usar un backslash vamos a tener que
poner dos backslash juntos.

• win_file = 'eek\\urk\\snort.txt'
• print(win_file) → 'eek\urk\snort.txt'

Si tenemos que armar una ruta hacia un archivo o directorio tenemos como alternativas:

• Usar el carácter de separación de rutas apropiado al sistema: '/' o '\'


• Construir la ruta al archivo utilizando os.path.join().

Obtener la ruta absoluta a un archivo con abspath()

• Esta función expande el nombre relativo a uno absoluto.

Construir la ruta con os.path.join()

• import os
• win_file = os.path.join("eek", "urk")
• win_file = os.path.join(win_file, "snort.txt")

Si ejecutamos lo anterior en sistemas Mac o Linux vamos a obtener:

• win_file → 'eek/urk/snort.txt'

Corriéndolo en Windows tendremos:

• win_file → 'eek\urk\snort.txt'

JSON

JSON es el acrónimo de JavaScript Object Notation. Es un formato de intercambio de información, que en los últimos
años se ha vuelto muy popular más allá de sus orígenes en JavaScript.

El formato JSON es un subconjunto de JavaScript y comúnmente su sintaxis es válida en Python también.

En ambientes de desarrollo Web, es muy utilizado para el intercambio de información entre programas.

El módulo más popular de Python para tratar con datos en formato Python se llama justamente json.

Este módulo nos permite:

• Codificar (dumps) datos en un string en formato JSON.


• Decodificar (loads) un string con contenido en formato JSON nuevamente a tipos de datos de Python.

También podría gustarte