Interpretes Juan Garcia
Un interpretador es un programa informático capaz de analizar y ejecutar otros programas, escritos en un lenguaje Ingeniería en Licenciatura de se de alto nivel. Los intérpretes diferencian de los compiladores en que Sistemas Computacionales mientras estos traducen un programa UNIDEP desde su descripción en un lenguaje de Maestro: José Franco programación al Benito código de máquina del sistema, los intérpretes sólo realizan la Urrea traducción a medida que sea necesaria, típicamente, instrucción por instrucción, y normalmente no guardan el resultado de dicha traducción.
ÍNDICE Información institucional. _______________________________________________________2 Introducción. _________________________________________________________________4 Definición de intérprete._________________________________________________________5 Estructura de un intérprete.______________________________________________________6 Ventajas y desventajas de los intérpretes.___________________________________________7 Aplicación de los sistemas basados en intérpretes.____________________________________8 Tipos de intérpretes.___________________________________________________________10 Introducción a los análisis sintácticos._____________________________________________12
Portafolio de evidencias de la materia Intérpretes. José Juan Garcia Bórquez. T1. Investigación de conceptos. Depuración, errores sintácticos, errores semánticos, errores en tiempo de ejecución.___________________________________________________________13 T2. Programación imperativa, funcional, aspecto, arboles sintácticas.____________________15 T3. Matriz de transición de estado._______________________________________________18 Prácticas de clase modo consola en Python.________________________________________23 Resolución de ejercicios en SharpDevelop._________________________________________37
INFORMACIÓN INSTITUCIONAL • Misión La misión de UNIDEP es formar profesionales de éxito que cuenten con las actitudes, habilidades y conocimientos que demanda el sector productivo de la región. • Visión La Universidad del Desarrollo Profesional es una institución de educación superior de calidad, que ofrece programas presenciales y semipresenciales de bachillerato, profesional asociado, licenciatura, posgrado, diplomados y cursos en México y en el extranjero. Se distingue por facilitar a sus egresados la incorporación al mercado de trabajo, apoyada en una estrecha vinculación con el sector productivo y en planes de estudio pertinente y dinámico. Es reconocida por su modelo educativo profesionalizante, por la flexibilidad de su oferta académica impartida en ciclos continuos y por horarios y cuotas accesibles, acordes a la disponibilidad de tiempo y recursos económicos del alumno. Cuenta con profesores de amplia experiencia profesional y educativa. Sus instalaciones dentro de la ciudad permiten el fácil acceso. Cuenta con un modelo de administración sistematizado, participativo, operado por personal que es recompensado por su desempeño efectivo que le permite maximizar las aportaciones de sus socios y mantener finanzas sanas. • Lealtad Los Integrantes de la comunidad Universitaria consideramos la fidelidad como un valor excelso que enaltecemos en nuestro quehacer diario. • Justicia Los integrantes de la comunidad Universitaria actuamos con la constante y perpetua voluntad de dar a cada cual lo que le corresponde conforme a sus méritos o actos. 2
Portafolio de evidencias de la materia Intérpretes. José Juan Garcia Bórquez. • Honestidad Los integrantes de la comunidad universitaria actuamos con sinceridad y honradez en nuestras tareas y en congruencia entre los pensamientos, palabras y acciones. • Responsabilidad Los integrantes de la comunidad universitaria llevamos a cabo nuestras actividades con integridad, con sentido del propósito y apegados a los objetivos institucionales. • Esfuerzo Los integrantes de la comunidad universitaria usamos nuestra máxima energía para cumplir con los objetivos trazados. • Creatividad Los integrantes de la comunidad universitaria resolvemos los problemas con imaginación, conocimientos y con un espíritu de mejora continua.
INTRODUCCIÓN Intérprete o interpretador es un programa informático capaz de analizar y ejecutar otros programas, escritos en un lenguaje de alto nivel. Los intérpretes se diferencian de los compiladores en que mientras estos traducen un programa desde su descripción en un lenguaje de programación al código de máquina del sistema, los intérpretes sólo realizan la traducción a medida que sea necesaria, típicamente, instrucción por instrucción, y normalmente no guardan el resultado de dicha traducción. Algunos ejemplos de lenguajes que son normalmente interpretados en vez de compilados son: Perl PHP Javascript Logo ASP (hasta la versión 3) Python Tcl Ruby J# 3
Portafolio de evidencias de la materia Intérpretes. José Juan Garcia Bórquez. ASP
DEFINICIÓN DE INTÉRPRETE Un interpretador es un programa informático capaz de analizar y ejecutar otros programas, escritos en un lenguaje de alto nivel. Los intérpretes se diferencian de los compiladores en que mientras estos traducen un programa desde su descripción en un lenguaje de programación al código de máquina del sistema, los intérpretes sólo realizan la traducción a medida que sea necesaria, típicamente, instrucción por instrucción, y normalmente no guardan el resultado de dicha traducción.
Interpretar: ejecutar un programa escrito en un lenguaje de alto nivel traduciéndolo línea por línea. Compilar: traducir un programa escrito en un lenguaje de alto nivel a un lenguaje de bajo nivel de una vez, en preparación para la ejecución posterior.
Los intérpretes son a menudo usados para construir máquinas virtuales que enlazan la máquina de computación esperada por la semántica y la máquina de computación disponible en el hardware.
ESTRUCTURA DE UN INTÉRPRETE A la hora de construir un intérprete es conveniente utilizar una Representación Interna (RI) del lenguaje fuente a analizar. De esta forma, la organización interna de la mayoría de los intérpretes se descompone en los módulos: 5. Traductor a Representación Interna: Toma como entrada el código del programa P en Lenguaje Fuente, lo analiza y lo transforma a la representación interna correspondiente a dicho programa P. 2. Representación Interna (P/RI): 4
Portafolio de evidencias de la materia Intérpretes. José Juan Garcia Bórquez. La representación interna debe ser consistente con el programa original. Entre los tipos de representación interna, los árboles sintácticos son los más utilizados y, si las características del lenguaje lo permiten, pueden utilizarse estructuras de pila para una mayor eficiencia. 3. Tabla de símbolos: Durante el proceso de traducción, es conveniente ir creando una tabla con información relativa a los símbolos que aparecen. La información a almacenar en dicha tabla de símbolos depende de la complejidad del lenguaje fuente. Se pueden almacenar etiquetas para instrucciones de salto, información sobre identificadores (nombre, tipo, línea en la que aparecen, etc.) o cualquier otro tipo de información que se necesite en la etapa de evaluación. 4. Evaluador de Representación Interna: A partir de la Representación Interna anterior y de los datos de entrada, se llevan a cabo las acciones indicadas para obtener los resultados. Durante el proceso de evaluación es necesario contemplar la aparición de errores. 5. Tratamiento de errores: Durante el proceso de evaluación pueden aparecer diversos errores como desbordamiento de la pila, divisiones por cero, etc. Que el intérprete debe contemplar.
Ventajas y desventajas de un intérprete Ventajas de un intérprete: *Flexibilidad: permite realizar acciones complejas, imposibles o muy difíciles con un compilador, como las siguientes: • Ejecución de cadenas de caracteres mediante operadores como "execute", "interprete" o "evalquote". • Modificar sobre la marcha el significado de los símbolos e incluso prescindir por completo de las declaraciones. • Obtener un ligamiento dinámico completo en los sistemas orientados a objetos. • Simplificar la gestión de memoria en los programas fuente. *Facilidad de depuración de programas: la interpretación puede interrumpirse en cualquier momento para examinar o modificar los valores de las variables o la situación en la ejecución. La tabla de símbolos está disponible. Se pueden corregir los errores y continuar. Trazas y paradas programadas. Saltos en el programa. Abandonos de subrutinas. *Rapidez en el desarrollo. Desventajas de un intérprete: *Velocidad: usualmente un orden de magnitud menor que la de un programa compilado. *Tamaño del programa objeto, que exige añadir el intérprete al programa propiamente dicho.
5
Portafolio de evidencias de la materia Intérpretes. José Juan Garcia Bórquez.
APLICACIÓN DE LOS SISTEMAS BASADOS EN INTÉRPRETES Los sistemas interpretados han tenido una gran importancia desde la aparición de los primeros ordenadores. En la actualidad, la evolución del hardware abre nuevas posibilidades a los sistemas interpretados. La preocupación ya no es tanto la eficiencia como la capacidad de desarrollo rápido de nuevas aplicaciones. Las principales aplicaciones podrían resumirse en: Intérpretes de Comandos: Los sistemas operativos cuentan con intérpretes de comandos como el Korn-Shell, C-Shell, JCL, etc. Estos intérpretes toman un lenguaje fuente que puede incluir sentencias de control (bucles, condiciones, asignaciones, etc.) y ejecutan los diferentes comandos a medida que aparecen en el lenguaje. Lenguajes basados en Escritos (Scripting Languages), diseñados como herramientas que sirvan de enlace entre diferentes sistemas o aplicaciones. Suelen ser interpretados con el fin de admitir una mayor flexibilidad a la hora de afrontar las peculiaridades de cada sistema. Podrían destacarse Perl, Tcl/Tk, JavaScript, WordBasic [Ousterhout 97] Entornos de Programación: Existen ciertos lenguajes que contienen características que impiden su compilación o cuya compilación no es efectiva. Estos lenguajes suelen disponer de un complejo entorno de desarrollo interactivo con facilidades para la depuración de programas. Entre estos sistemas pueden destacarse los entornos de desarrollo para Lisp, Visual Basic, Smalltalk, etc. Lenguajes de Propósito Específico: Ciertos lenguajes incluyen sentencias que realizan tareas complejas en contextos específicos. Existe una gran variedad de aplicaciones en las que se utilizan este tipo de lenguajes como consultas de Bases de Datos, simulación, descripción de hardware, robótica, CAD/CAM, música, etc. Sistemas en Tiempo Real: Entornos que permiten modificar el código de una aplicación en tiempo de ejecución de forma interactiva. Intérprete de Código Intermedio: Una tendencia tradicional en el diseño de compiladores es la generación de un código intermedio para una máquina abstracta, por ejemplo, el P-Code de Pascal o los bytecodes de Java. El siguiente paso puede ser: generación del código objeto a partir del código intermedio para una máquina concreta, finalizando el proceso de compilación o interpretar dicho código intermedio en una máquina concreta. La tendencia habitual es definir un lenguaje intermedio independiente de una máquina concreta. Para ello, suele definirse una máquina virtual que contenga las instrucciones definidas por el lenguaje intermedio, permitiendo una mayor portabilidad. Un ejemplo sería la Máquina Virtual de Java, que es simulada en la mayoría de los visualizadores Web.
6
Portafolio de evidencias de la materia Intérpretes. José Juan Garcia Bórquez.
Figura 5: Esquema de Compilador con Intérprete de código intermedio En la siguiente tabla, tomada de [Hudak, 98] se resumen algunos de los principales lenguajes de propósito específico con sus respectivas aplicaciones.
TIPOS DE INTÉRPRETES En función de la estructura interna de intérprete se pueden distinguir: • Interpretes puros • Interpretes avanzados • Interpretes incrementales • Evaluadores parciales • Compiladores “Just in time” • Compilación continua Interpretes puros 7
Portafolio de evidencias de la materia Intérpretes. José Juan Garcia Bórquez. Analizan y ejecutan todo el programa fuente sentencia a sentencia. • Pensados para maquinas con limitación de memoria • Si a la mitad del programa se producen errores entonces hay que volver a ejecutar desde el inicio. • Todas las instrucciones en RI están etiquetadas o consecutivas en una estructura fija (array). • El evaluador de instrucciones determina la instrucción que debe ejecutarse y los datos de entrada que necesita o emite un error. Interpretes avanzados Avanzados o normales • Incorporan un paso previo de análisis de todo el programa fuente • Genera posteriormente un lenguaje RI ejecutado por el interprete • Se usa para lenguajes más avanzados, ya que permite otro tipo de análisis y optimizaciones Interpretes incrementales Dirigidos a lenguajes que no pueden compilarse • Pueden crear objetos o funciones en tiempo de ejecución (Lisp, Prolog, Smalltalk) • Se compilan las partes estáticas • Posteriormente, en tiempo de ejecución se compilan las partes dinámicas requeridas (o recompilan las modificadas) • No producen código objeto independiente, vienen acompañados de módulos que en tiempo de ejecución permiten la compilación (run time system) Evaluaciones parciales (especializadores) • Programas con dos tipos de datos de entrada • Se gana eficiencia cuando es conocido que un programa va a ejecutarse muchas veces sobre un mismo conjunto de datos • Binding-time analysis es una técnica para determinar los datos estáticos Binding-time analysis => Análisis del tiempo de unión. Compiladores “Just in time” • • •
Surgen con la necesidad de distribuir programas independientes de la maquina Para evitar la interpretación los códigos de bytes se transforman a código nativo El código es compilado a código nativo justo en el momento que lo necesita el programa
8
Portafolio de evidencias de la materia Intérpretes. José Juan Garcia Bórquez. Compilación continua Mejora de “Just in time” Mezcla compilación a código nativo con la interpretación Dispone de dos módulos: Un intérprete de código de bytes Un compilador de código de bytes a código natico Deberían actuar a la vez El código es mezcla de código fuente nativo Al principio está todo sin compilar, a medida que el programa es ejecutado el compilador va generando traducciones a código nativo
Investigación de conceptos ¿Qué es la depuración (Debugging)?
9
Portafolio de evidencias de la materia Intérpretes. José Juan Garcia Bórquez. Un depurador es un programa usado para probar y depurar (eliminar errores) de otros programas. El código a ser examinado puede alternativamente estar corriendo en un simulador de conjuntos de instrucciones (ISS), una técnica que permite gran potencia en su capacidad de detenerse cuando son encontrados condiciones específicas pero será típicamente algo más lento que ejecutando el código directamente en el apropiado (o el mismo) procesador. Algunos depuradores ofrecen dos modos de operación – la simulación parcial o completa, para limitar este impacto. ¿Qué son los errores sintácticos? Este tipo de errores siempre son detectados por el ‘compilador’, antes de ejecutar el programa. A los errores tipográficos, como por ejemplo la falta de puntos y comas, nombres de variables incorrectas, la falta de paréntesis, palabras claves mal escritas, etc. Los llamamos errores ‘sintácticos’. Un programa no se puede ejecutar sin corregir absolutamente todos los errores sintácticos. ¿Qué son los errores en tiempo de ejecución? Un error en tiempo de ejecución es un problema de hardware o software que impide que un programa funcione correctamente. Los errores en tiempo de ejecución pueden ocasionar la perdida de información en el archivo en el que se está trabajando, causar errores en el archivo (dañándolo) de forma que no pueda trabajar con él o impedir que use una característica. Al contrario que los errores de detención, los errores en tiempo de ejecución no suelen ser la causa que un programa deje de funcionar. Los errores en tiempo de ejecución poder producir si está ejecutando dos programas de software que no son compatibles, si el equipo tiene problemas de memoria o si el equipo está infectado con software malintencionado.
¿Que son los errores semánticos? Este error se produce cuando la sintaxis del código es correcta, pero la semántica o significado no es el que se pretendía. La construcción obedece las reglas del lenguaje, y por ello el compilador o intérprete no detectan los errores semánticos. Los compiladores e intérpretes solo se ocupan de la estructura del código que se escribe, y no de su significado. Un error semántico puede hacer que el programa termine de forma anormal, con o sin un mensaje de error. Hablando en términos coloquiales, puede hacer que el equipo se quede colgado.
10
Portafolio de evidencias de la materia Intérpretes. José Juan Garcia Bórquez.
Programación imperativa, funcional, aspecto, arboles sintácticas Programación imperativa En contraposición a la programación declarativa es un paradigma de programación que describe la programación en términos del estado del programa y sentencias que cambian dicho estado. Los programas imperativos son un conjunto de instrucciones que le indican al computador cómo realizar una tarea. La implementación de hardware de la mayoría de computadores es imperativa; prácticamente todo el hardware de los computadores está diseñado para ejecutar código de máquina, que es nativo al computador, escrito en una forma imperativa. Esto se debe a que el hardware de los computadores implementa el paradigma de las Máquinas de Turing. Desde esta perspectiva de bajo nivel, el estilo del programa está definido por los contenidos de la memoria, y las sentencias son instrucciones en el lenguaje de máquina nativo del computador (por ejemplo el lenguaje ensamblador). Los lenguajes imperativos de alto nivel usan variables y sentencias más complejas, pero aún siguen el mismo paradigma. Las recetas y las listas de revisión de procesos, a pesar de no ser programas de computadora, son también conceptos familiares similares en estilo a la programación imperativa; donde cada paso es una instrucción. Los primeros lenguajes imperativos fueron los lenguajes de máquina de los computadores originales. En estos lenguajes, las instrucciones fueron muy simples, lo cual hizo la implementación de hardware fácil, pero obstruyendo la creación de programas complejos. Fortran, cuyo desarrollo fue iniciado en 1954 por John Backus en IBM, fue el primer gran lenguaje de programación en superar los obstáculos presentados por el código de máquina en la creación de programas complejos. Programación funcional Es un paradigma de programación declarativa basado en la utilización de funciones aritméticas que no maneja datos mutables o de estado. Enfatiza la aplicación de funciones, en contraste con el estilo de programación imperativa, que enfatiza los cambios de estado. La programación funcional tiene sus raíces en el cálculo lambda, un sistema formal desarrollado en los 1930s para investigar la definición de función, la aplicación de las funciones y la recursión. Muchos lenguajes de programación funcionales pueden ser vistos como elaboraciones del cálculo lambda. En la práctica, la diferencia entre una función matemática y la noción de una "función" utilizada en la programación imperativa es que las funciones imperativas pueden tener efectos secundarios, al cambiar el valor de cálculos realizados previamente. Por esta razón carecen de transparencia referencial, es decir, la misma expresión sintáctica 11
Portafolio de evidencias de la materia Intérpretes. José Juan Garcia Bórquez. puede resultar en valores diferentes en diferentes momentos dependiendo del estado del programa siendo ejecutado. Con código funcional, en contraste, el valor generado por una función depende exclusivamente de los argumentos alimentados a la función. Al eliminar los efectos secundarios se puede entender y predecir el comportamiento de un programa mucho más fácilmente, y esta es una de las principales motivaciones para utilizar la programación funcional. Los lenguajes de programación funcional, especialmente los que son puramente funcionales, han sido enfatizados en el ambiente académico principalmente y no tanto en el desarrollo de software comercial. Sin embargo, lenguajes de programación importantes tales como Scheme, Erlang, Rust, Objective Caml y Haskell, han sido utilizados en aplicaciones comerciales e industriales por muchas organizaciones. La programación funcional también es utilizada en la industria a través de lenguajes de dominio específico como R (estadística), Mathematica (matemáticas simbólicas), J y K (análisis financiero), F# en Microsoft.NET y XSLT (XML). Lenguajes de uso específico usados comúnmente como SQL y Lex/Yacc, utilizan algunos elementos de programación funcional, especialmente al procesar valores mutables. Las hojas de cálculo también pueden ser consideradas lenguajes de programación funcional. La programación funcional también puede ser desarrollada en lenguajes que no están diseñados específicamente para la programación funcional. En el caso de Perl, por ejemplo, que es un lenguaje de programación imperativo, existe un libro que describe cómo aplicar conceptos de programación funcional. JavaScript, uno de los lenguajes más ampliamente utilizados en la actualidad, también incorpora capacidades de programación funcional. Python también incorpora particularidades de los lenguajes funcionales como listas de comprensión y funciones de tratamiento de listas como matemática de conjuntos.
Los arboles sintácticos Es una clase especial de árbol, se le denomina Árbol Sintáctico es una forma condensada de un árbol de análisis sintáctico, útil para representar instrucciones de lenguajes. Un árbol sintáctico permite demostrar que una secuencia de caracteres es una determinada categoría sintáctica. Llevan su nombre en base a la función que cumple, donde cada nodo representa una operación y los hijos de un nodo son los argumentos de la operación. Un árbol sintáctico puede cumplir tres funciones diferentes: • Comprobar el orden en que llegan los tokens (componente léxico es una cadena de caracteres) • Construir una representación del programa fuente. • Si es sintácticamente correcto generar el error Un Árbol Sintáctico bien realizado se caracteriza por ser una representación abstracta que va desde las sub-categorías hasta la categoría general, por constar de operadores en nodos no terminales y operandos en nodos terminales.
12
Portafolio de evidencias de la materia Intérpretes. José Juan Garcia Bórquez.
Programación orientada a aspectos Es un paradigma de programación relativamente reciente cuya intención es permitir una adecuada modularización de las aplicaciones y posibilitar una mejor separación de incumbencias. Gracias a la POA se pueden encapsular los diferentes conceptos que componen una aplicación en entidades bien definidas, eliminando las dependencias entre cada uno de los módulos. De esta forma se consigue razonar mejor sobre los conceptos, se elimina la dispersión del código y las implementaciones resultan más comprensibles, adaptables y reusables. Varias tecnologías con nombres diferentes se encaminan a la consecución de los mismos objetivos y así, el término POA es usado para referirse a varias tecnologías relacionadas como los métodos adaptativos, los filtros de composición, la programación orientada a sujetos o la separación multidimensional de competencias. MATRIZ DE TRANSICION DE ESTADOS. Esta es una matriz cuadrada, donde el número de renglones y de columnas será igual al de estados que tenga la cadena de Markov, siendo cada elemento de la matriz, la probabilidad de transición respectiva de pasar del estado que encabeza el renglón donde está ubicado el elemento hacia el estado encabezado por la columna. Miremos el siguiente ejemplo:
Se observa que para el primer renglón las probabilidades de transición indican que habrá un 50% de los clientes fieles a la marca A, por su parte un 30% cambiara de A B y un 20% cambiara de A C. Obsérvese que la suma se probabilidades de cada renglón es igual a 1. Una manera de visualizar mejor la tabla dada anteriormente es a través de un diagrama de estado. Aquí los estados se indican a través de círculos y las flechas que salen de ellos son las probabilidades de que sus clientes cambien a otro estado. Es decir, las 13
Portafolio de evidencias de la materia Intérpretes. José Juan Garcia Bórquez. flechas que regresan al mismo estado del que salen, señalan las probabilidades de que los clientes sean retenidos por esa marca en particular. CALCULO DE PROBABILIDADES DE LA MATRIZ DE TRANSICIÓN Para hallar las probabilidades de los estados dentro de la matriz de transición en un periodo determinado procedemos de la siguiente manera como se muestra en el siguiente ejemplo:
Las granjas de cierta región se pueden clasificar con 3 tipos: agrícolas, pecuarias o mixtas. Actualmente 30% son agrícolas, 40% pecuarias y 30% son mixtas. La matriz de transición de un año al siguiente es:
De acuerdo a la información dada, el Po es:
Para hallar el valor de las probabilidades en el año siguiente hacemos uso de la multiplicación de las matrices, como sigue Para el estado A:
Por lo que el vector para el año siguiente es:
14
Portafolio de evidencias de la materia Intérpretes. José Juan Garcia Bórquez. De igual manera calculamos el porcentaje para cada tipo de granja para el periodo 2, 3, 4y5
Obsérvese que el valor de la probabilidad de un estado n está dado por la siguiente expresión:
MATRIZ DE TRANSICIÓN EN ESTADO ESTABLE Un estado es estable cuando ya no hay cambios en el sistema, es decir que se alcanza el equilibrio. Una manera posible de obtener las condiciones del sistema para el estado estable es repetir iterativamente los cálculos para cada periodo con el fin de hallar el periodo con aquellas probabilidades que se mantienen constantes o no cambian. Sin embargo también es posible utilizar los métodos para resolver sistemas de ecuaciones que nos permiten encontrar directamente estas probabilidades de estado estables. Dado el ejemplo anterior acerca de los tipos de granjas, calcularemos los estados estables a través de los métodos para sistemas de ecuaciones. En primera medida lo que hacemos es hallar la traspuesta de la matriz de transición, es decir:
El sistema de ecuaciones quedaría así:
15
Portafolio de evidencias de la materia Intérpretes. José Juan Garcia Bórquez.
Esta última ecuación es agregada siguiendo la propiedad de que la sumatoria las probabilidades de los estados debe ser igual a 1.
Utilizando el método de eliminación, restamos las ecuaciones (1) y (2) eliminando z.
Ahora sumamos las ecuaciones (3) y (4), multiplicando la ecuación 4 por 0.2 con el fin de eliminar z
Despejando de la ecuación (6) y reemplazando en (5), tenemos:
16
Portafolio de evidencias de la materia Intérpretes. José Juan Garcia Bórquez.
Reemplazando x en (6)
17
Portafolio de evidencias de la materia Intérpretes. José Juan Garcia Bórquez.
Practica 1 en Iron Python Variables, expresiones y sentencias Valores y tipos Los valores pertenecen a diferentes tipos: 2 es un entero, y "Hola, Mundo!" es una cadena, llamada así porque contiene una “cadena” de letras. Usted (y el intérprete) pueden identificar cadenas porque están encerradas entre comillas. La sentencia de impresión también trabaja con enteros. >>> print 4 4 Si no está seguro del tipo que un valor tiene, el intérprete le puede decir. >>> type("Hola, Mundo!") <type ’string’> >>> type(17) <type ’int’> >>> type(3.2) <type ’float’> ¿Qué ocurre con valores como "17" y "3.2"? Parecen números, pero están encerrados entre comillas como las cadenas. >>> type("17") <type ’string’> Ellos son cadenas. >>> type("3.2") <type ’string’>
Variables
Una de las características más poderosas en un lenguaje de programación es la capacidad de manipular variables. Una variable es un nombre que se refiere a un valor. La sentencia de asignación crea nuevas variables y les da valores: >>> mensaje = "¿Qué Onda?" >>> n = 17 >>> pi = 3.14159 La sentencia print también funciona con variables. >>> print mensaje Qué Onda? >>> print n 17 >>> print pi 3.14159 En cada caso el resultado es el valor de la variable. Las variables también tienen tipos; nuevamente, le podemos preguntar al intérprete cuales son. >>> type(mensaje) <type ’string’> >>> type(n) <type ’int’> >>> type(pi) <type ’float’> El tipo de una variable es el mismo del valor al que se refiere.
18
Portafolio de evidencias de la materia Intérpretes. José Juan Garcia Bórquez.
Nombres de variables y palabras reservadas Los programadores, generalmente, escogen nombres significativos para sus variables —que especifiquen para qué se usa la variable. Estos nombres pueden ser arbitrariamente largos. Pueden contener letras y números, pero tienen que empezar con una letra. Aunque es legal usar letras mayúsculas, por convención no lo hacemos. Si usted lo hace, recuerde que la capitalización importa, Pedro y pedro son variables diferentes. El carácter subrayado ( _) puede aparecer en un nombre. A menudo se usa en nombres con múltiples palabras, tales como mi_nombre o precio_del_café_en_china. Si usted le da un nombre ilegal a una variable obtendrá un error sintáctico: >>> 76trombones = "gran desfile" SyntaxError: invalid syntax 76trombones es ilegal porque no empieza con una letra. >>> mas$ = 1000000 SyntaxError: invalid syntax mas$ es ilegal porque contiene un carácter ilegal, el símbolo $. >>> class = "introducción a la programación" SyntaxError: invalid syntax ¿Qué sucede con class? Resulta que class es una de las palabras reservadas (keywords) de Python. Las palabras reservadas definen las reglas del lenguaje y su estructura, y no pueden ser usadas como nombres de variables. Python tiene veintiocho palabras reservadas: and continue else for import not assert def except from in or break del exec global is pass class elif finally if lambda print raise return try while
Evaluando expresiones Una expresión es una combinación de valores, variables y operadores. Si usted digita una expresión en la línea de comandos, el intérprete la avalúa y despliega su resultado: >>> 1 + 1 2 Un valor, por sí mismo, se considera como una expresión, lo mismo ocurre para las variables. >>> 17 17 Aunque es un poco confuso, evaluar una expresión no es lo mismo que imprimir o desplegar un valor. >>> mensaje = "Como le va, Doc?" >>> mensaje "Como le va, Doc?" >>> print mensaje Como le va, Doc? Cuando Python muestra el valor de una expresión que ha evaluado, utiliza el mismo formato que se usaría para entrar un valor. En el caso de las cadenas, esto Implica que se incluyen las comillas. Cuando se usa la sentencia print, el efecto es distinto como usted ya lo ha evidenciado.
19
Portafolio de evidencias de la materia Intérpretes. José Juan Garcia Bórquez.
Operadores y operandos
Los operadores son símbolos especiales que representan cómputos, como la suma y la multiplicación. Los valores que el operador usa se denominan operandos. Los siguientes son expresiones validas en Python, cuyo significado es más o menos claro: 20+32 hora-1 hora*60+minuto minuto/60 5**2 (5+9)*(15-7) Los símbolos +, -, y /, y los paréntesis para agrupar, significan en Python lo mismo que en la matemática. El asterisco (*) es el símbolo para la multiplicación, y ** es el símbolo para la exponenciación. Cuando el nombre de una variable aparece en lugar de un operando, se reemplaza por su valor antes de calcular la operación La suma, resta, multiplicación y exponenciación realizan lo que usted esperaría, pero la división podría sorprenderlo. La siguiente operación tiene un resultado inesperado: >>> minuto = 59 >>> minuto/60 0 El valor de minuto es 59, y 59 dividido por 60 es 0.98333, no 0. La razón para esta discrepancia radica en que Python est{a realizando división entera. Cuando los dos operandos son enteros el resultado también debe ser un entero; y, por convención, la división entera siempre redondea hacia abajo, incluso en casos donde el siguiente entero está muy cerca.
Orden de las operaciones Cuando hay más de un operador en una expresión, el orden de evaluación depende de las reglas de precedencia. Python sigue las mismas reglas de precedencia a las que estamos acostumbrados para sus operadores matemáticos. El acrónimo PEMDAS es útil para recordar el orden de las operaciones: Los Paréntesis tienen la precedencia más alta y pueden usarse para forzar la evaluación de una expresión de la manera que usted desee. Ya que las expresiones en paréntesis se evalúan primero: 2 * (3-1) es 4, y (1+1)**(5-2) es 8. Usted también puede usar paréntesis para que una expresión quede más legible, como en (minuto * 100) / 60, aunque esto no cambie el resultado. La Exponenciación tiene la siguiente precedencia más alta, así que 2**1+1 es 3 y no 4, y 3*1**3 es 3 y no 27. La Multiplicación y la División tienen la misma precedencia, aunque es más alta que la de la Adición y la Sustracción, que también tienen la misma precedencia. Así que 2*3-1 es 5 en lugar de 4, y 2/3-1 es -1, no 1 (recuerde que en división entera, 2/3=0). Los operadores con la misma precedencia se evalúan de izquierda a derecha. minuto=59, en la expresión minuto*100/60; la multiplicación se hace primero, resultando 5900/60, lo que a su vez da 98. Si las operaciones se hubieran evaluado de derecha a izquierda, el resultado sería 59/1, que es 59, y no es lo correcto.
Operaciones sobre cadenas En general, usted no puede calcular operaciones matemáticas sobre cadenas, incluso si las cadenas lucen como números. Las siguientes operaciones son ilegales (asumiendo que mensaje tiene el tipo cadena):
20
Portafolio de evidencias de la materia Intérpretes. José Juan Garcia Bórquez. mensaje-1 "Hola"/123 mensaje*"Hola" "15"+2 Sin embargo, el operador + funciona con cadenas, aunque no calcula lo que usted esperaría. Para las cadenas, el operador + representa la concatenación, que significa unir los dos operandos enlazándolos en el orden en que aparecen. Por ejemplo: fruta = "banano" bienCocinada = " pan con nueces" >>>print fruta + bienCocinada La salida de este programa es: banano pan con nueces. El espacio antes de la palabra pan es parte de la cadena y sirve para producir el espacio entre las cadenas concatenadas. El operador * también funciona con las cadenas; hace una repetición. Por ejemplo, ’Fun’*3 es ’FunFunFun’. Uno de los operandos tiene que ser una cadena, el otro tiene que ser un entero. Estas interpretaciones de + y * tienen sentido por la analogía con la suma y la multiplicación. Así como 4*3 es equivalente a 4+4+4, esperamos que "Fun"*3 sea lo mismo que "Fun"+"Fun"+"Fun", y lo es.
21
Portafolio de evidencias de la materia Intérpretes. José Juan Garcia Bórquez.
Practica 2 en Iron Python Composición Hasta aquí hemos considerado a los elementos de un programa—variables, expresiones y sentencias—aisladamente, sin especificar como combinarlos. Una de las características más útiles de los lenguajes de programación es su capacidad de tomar pequeños bloques para componer con ellos. Por ejemplo, ya que sabemos cómo sumar números y cómo imprimirlos; podemos hacer las dos cosas al mismo tiempo: >>> print 17 + 3 20 De hecho, la suma tiene que calcularse antes que la impresión, así que las acciones no están ocurriendo realmente al mismo tiempo. El punto es que cualquier expresión que tenga números, cadenas y variables puede ser usada en una sentencia de impresión (print). Usted ha visto un ejemplo de esto: >>>minuto=60 >>>hora=60 >>>print "Número de minutos desde media noche: ", hora*60+minuto
Comentarios A medida que los programas se hacen más grandes y complejos, se vuelven más difíciles de leer. Los lenguajes formales son densos; y, a menudo, es difícil mirar una sección de código y saber qué hace, o por qué lo hace. Por esta razón, es una muy buena idea a ˜nadir notas a sus programas para explicar, en lenguaje natural, lo que hacen. Estas notas se denominan comentarios y se marcan con el símbolo #: >>># calcula el porcentaje de la hora que ha pasado >>>porcentaje = (minuto * 100) / 60 En este caso, el comentario aparece en una línea completa. También pueden ir comentarios al final de una línea: >>># precaución: división entera porcentaje = (minute * 100) / 60
Glosario
Valor: un número o una cadena (u otra cosa que se introduzca más adelante) que puede ser almacenado en una variable o calculado en una expresión. Tipo: conjunto de valores. El tipo del valor determina como se puede usar en expresiones. Hasta aquí, los tipos que usted ha visto son enteros (tipo int), números de punto flotante (tipo float) y cadenas (tipo string). Punto flotante: formato para representar números con parte decimal. Variable: nombre que se refiere a un valor. Sentencia: sección de código que representa un comando o acción. Hasta aquí las sentencias que usted ha visto son la de asignación y la de impresión. Asignación: corresponde a la sentencia que pone un valor en una variable. Palabra reservada: es una palabra usada por el compilador para analizar sintácticamente un programa; usted no puede usar palabras reservadas como if, def, y while como nombres de variables. Operador: símbolo especial que representa un simple cálculo como una suma, multiplicación o concatenación de cadenas. Operando: uno de los valores sobre el cual actúa un operador. Expresión: combinación de variables, operadores y valores que representa un único valor de resultado. Evaluar: simplificar una expresión ejecutando varias operaciones a fin de retornar un valor único.
22
Portafolio de evidencias de la materia Intérpretes. José Juan Garcia Bórquez. División entera: operación que divide un entero por otro y retorna un entero. La división entera retorna el número de veces que el denominador cabe en el numerador y descarta el residuo. Reglas de precedencia: reglas que gobiernan el orden en que las expresiones que tienen múltiples operadores y operandos se evalúan. Concatenar: unir dos operandos en el orden en que aparecen. Composición: es la capacidad de combinar simples expresiones y sentencias dentro de sentencias y expresiones compuestas para representar cálculos complejos concisamente. Comentario: información que se incluye en un programa para otro programador (o lector del código fuente) que no tiene efecto en la ejecución.
Conversión de tipos Python proporciona una colección de funciones que convierten valores de un tipo a otro. La función int toma cualquier valor y lo convierte a un entero, si es posible, de lo contrario se queja: >>> int("32") 32 >>> int("Hola") ValueError: invalid literal for int(): Hola int también puede convertir valores de punto flotante a enteros, pero hay que tener en cuenta que va a eliminar la parte decimal: >>> int(3.99999) 3 >>> int(-2.3) -2 La función float convierte enteros y cadenas a número de punto flotante: >>> float(32) 32.0 >>> float("3.14159") 3.14159 Finalmente, la función str convierte al tipo cadena (string): >>> str(32) ’32’ >>> str(3.14149) ’3.14149’
Coerción de tipos Ahora que podemos convertir entre tipos, tenemos otra forma de esquivar a la división entera. Retomando el ejemplo del capítulo anterior, suponga que deseamos calcular la fracción de una hora que ha transcurrido. La expresión más obvia minuto/60, hace división entera, así que el resultado siempre es 0, incluso cuando han transcurrido 59 minutos. Una solución es convertir minuto a punto flotante para realizar la división en punto flotante: >>> minuto = 59 >>> float(minute)/60.0 0.983333333333 Otra alternativa es sacar provecho de las reglas de conversión automática de tipos, que se denominan coerción de tipos. Para los operadores matemáticos, si algún operando es un número flotante, el otro se convierte automáticamente a flotante: >>> minuto = 59 >>> minuto / 60.0 0.983333333333 Así que haciendo el denominador flotante, forzamos a Python a realizar división en punto flotante.
23
Portafolio de evidencias de la materia Intérpretes. José Juan Garcia Bórquez.
Practica 3 en Iron Python Operadores aritméticos Operador Descripció n + Suma
Ejemplo r = 3 + 2 # r es 5
-
Resta
Operado r -
Descripción
Ejemplo
Negación
r = -7 # r es -7
*
Multiplicación
r = 2 * 6 # r es 12
**
Exponente
r = 2 ** 6 # r es 64
/
División
r = 3.5 / 2 # r es 1.75
//
División entera r = 3.5 // 2 # r es 1.0
%
Módulo
r = 4 - 7 # r es -3
r = 7 % 2 # r es 1
Booleanos Una variable de tipo booleano sólo puede tener dos valores:
True (cierto)
y False (falso).
Estos son los distintos tipos de operadores con los que podemos trabajar con valores booleanos, los llamados operadores lógicos o condicionales: Operado r and
Descripción
Ejemplo
or
¿Se cumple a o b? r = True or False # r es True
not
No a
¿Se cumple a y b? r = True and False # r es False
r = not True # r es False
Los valores booleanos son además el resultado de expresiones que utilizan operadores relacionales (comparaciones entre valores): Operado r ==
Descripción
Ejemplo
¿son iguales a y b?
r = 5 == 3 # r es False
!=
¿son distintos a y b? r = 5 != 3 # r es True 24
Portafolio de evidencias de la materia Intérpretes. José Juan Garcia Bórquez. <
¿es a menor que b?
r = 5 < 3 # r es False
>
¿es a mayor que b?
r = 5 > 3 # r es True
< = > =
¿es a menor o igual que r = 5 <= 5 # r es True b? ¿es a mayor o igual que b? r = 5 >= 3 # r es True
Listas La lista es un tipo de colección ordenada. Sería equivalente a lo que en otros lenguajes se conoce por arrays, o vectores. Las listas pueden contener cualquier tipo de dato: números, cadenas, booleanos, … y también listas. Crear una lista es tan sencillo como indicar entre corchetes, y separados por comas, los valores que queremos incluir en la lista: >>>a = [22, True, “una lista”, [1, 2]] Podemos acceder a cada uno de los elementos de la lista escribiendo el nombre de la lista e indicando el índice del elemento entre corchetes. NOTA: Ten en cuenta que el índice del primer elemento de la lista es 0, y no 1: >>>a[2] ‘una lista’ >>>a[0] 22 Si queremos acceder a un elemento de una lista incluida dentro de otra lista. >>> a = [22, True, “una lista”, [1, 2]] Tendremos que utilizar dos veces este operador, primero para indicar a qué posición de la lista exterior queremos acceder, y el segundo para seleccionar el elemento de la lista interior: si queremos el valor 1 de la sublista [1,2] >>>a[3][0] 1 También podemos utilizar este operador para modificar un elemento de la lista si lo colocamos en la parte izquierda de una asignación: >>> a = [22, True, “una lista”, [1, 2]] >>>a[0] 22 25
Portafolio de evidencias de la materia Intérpretes. José Juan Garcia Bórquez. >>>a[0] =99 >>>a[0] 99 Una curiosidad sobre el operador [] de Python es que podemos utilizar también números negativos. Si se utiliza un número negativo como índice, esto se traduce en que el índice empieza a contar desde el final, hacia la izquierda; es decir, con [-1] accederíamos al último elemento de la lista, con [-2] al penúltimo, con [-3], al antepenúltimo, y así sucesivamente. >>>a = [22, True, “una lista”, [1, 2]] >>>a[-1] [1,2]
Sentencias condicionales Aquí es donde cobran su importancia el tipo booleano y los operadores lógicos y relacionales que aprendimos en el capítulo sobre los tipos básicos de Python.
if La forma más simple de un estamento condicional es un if (del inglés si) seguido de la condición a evaluar, dos puntos (:) y en la siguiente línea e indentado, el código a ejecutar en caso de que se cumpla dicha condición. >>> valor=”programa” >>> if valor == “programa” : print “Respuesta correcta”
if … else >>> valor=”programa” >>> if valor == “programa” : print “Respuesta correcta” …else: print “respuesta incorrecta” Respuesta correcta
if … elif … elif … else elif es una contracción de else if, por lo tanto elif numero > 0 puede leerse como “si no, si numero es mayor que 0”. Es decir, primero se evalúa la condición del if. Si es cierta, se ejecuta su código y se continúa ejecutando el código posterior al condicional; si no se cumple, se evalúa la condición del elif. Si se cumple la condición del elif se ejecuta su código y se continua ejecutando el código posterior al condicional; si no se cumple y hay más de un elif se continúa con el siguiente en orden de aparición. Si no se cumple la condición del if ni de ninguno de los elif, se ejecuta el código del else.
>>>numero=1 >>>if numero >0: print “número positivo” …elif numero <0: print “número negativo” …else: print “Cero” número positivo 26
Portafolio de evidencias de la materia Intérpretes. José Juan Garcia Bórquez.
Practica 4 en Iron Python Entrada estándar La forma más sencilla de obtener información por parte del usuario es mediante la función raw_input. Esta función toma como parámetro una cadena a usar como prompt (es decir, como texto a mostrar al usuario pidiendo la entrada) y devuelve una cadena con los caracteres introducidos por el usuario hasta que pulsó la tecla Enter. Veamos un pequeño ejemplo: >>>nombre = raw_input(“dame tu nombre: “)
Definición de una Función >>> def imprimedoble(dato): … print dato dato Esta función toma un argumento y lo asigna a un parámetro llamado dato. El valor del parámetro (en este momento no tenemos idea de lo que será) se imprime dos veces. >>>imprimedoble(“azul”) azul azul >>>imprimedoble(“azul”*3) azulazulazul azulazulazul >>> def concatenarDoble(parte1, parte2): … cat = parte1 + parte2 … imprimaDoble(cat) >>>concatenarDoble(“uno”,”dos”) unodos unodos
27
Portafolio de evidencias de la materia Intérpretes. José Juan Garcia Bórquez. def conteo(n): if n == 0: print "Despegue!" else: print n conteo(n-1)
28
Portafolio de evidencias de la materia Intérpretes. José Juan Garcia Bórquez.
Practica 5 en Iron Python `Crear y ejecutar en el editor SharpDevelop la siguiente función de Ironpython
def conteo(n): if n == 0: print "Despegue!" else: print n conteo(n-1) a=raw_input("presiona enter") conteo(10) Crear y ejecutar en el editor SharpDevelop la siguiente lista de datos, y con la función len() contar el número de letras de cada palabra en la lista de datos. Utilice la instrucción for para revisar cada palabra de la lista.
palabras= ["windows","universidad","ingenieria de software","interpretes"] for i in palabras: print (i, len(i)) a=raw_input("presiona enter")
Crear y ejecutar en el editor SharpDevelop un programa que solicite la edad y nos indique cuantos días hemos vivido, además que se valide que se capturó un número y no una letra. try: 29
Portafolio de evidencias de la materia Intérpretes. José Juan Garcia Bórquez.
edad =raw_input("Cual es tu edad: ") dias=int(edad)*365 print "Has vivido " + str(dias) + " dias" a=raw_input("presiona enter") except ValueError: print "Eso no es un numero, verifica!" a=raw_input("presiona enter")
30
Portafolio de evidencias de la materia Intérpretes. José Juan Garcia Bórquez.
Resolución de ejercicios en SharpDevelop Calcula días vividos try: edad =raw_input("cual es tu edad: ") dias=int(edad)*365 print "has vovido " + str(dias) + " dias" a= raw_input("Presiona enter") except ValueError: print "Eso no es un numero, verifica!" a=raw_input("presiona enter") Operaciones basicas (Suma, Resta, Divicion, Multiplicacion y Elevacion) try: num1= raw_input("dame el primer numero: ") num2= raw_input("dame el segundo numero: ") suma= int(num1) + int(num2) print ("el resultado de la suma es: ", suma) resta= int(num1) - int(num2) print ("el resultado de la resta es: ", resta) multi= int(num1) * int(num2) print ("el resultado de la multiplicacion es: ", multi) elevado= int(num1)**int(num2) print ("el resultado del primer numero elevado al segundo numero es: ", elevado) if int(num2) !=0: div= float (num1) / float(num2) print ("el resultado de la division es: ", div) else: print("No puedes dividir un numero entre cero") a=raw_input("presiona enter para continuar") except ValueError: print ("Eso no es un numero, Verifica!") a=raw_input ("presiona enter para continuar") Tabla de Multiplicar a= raw_input("Que tabla de multiplicar quieres?: ") print "Tabla del: ", int(a) for variable in range(1,11): print a , "X", variable, "=",int(a) * variable e= raw_input("Presione enter para salir") Lista que muestra la longitud de las palabras palabras= ["windows","universidad","ingenieria de software","interpretes"] for i in palabras: print (i, len(i)) a=raw_input("presiona enter para continuar") Conteo para despegar def conteo (n): if n == 0: print "Despegue!" else:
31
Portafolio de evidencias de la materia Intérpretes. José Juan Garcia Bórquez. print n conteo(n-1) a=raw_input("presiona enter") conteo (10) b=raw_input("presiona enter para finalizar") Programa para guardar 3 palabras en una lista y poder modificarlas a= raw_input ("Dame la primer palabra: ") b= raw_input ("Dame la segunda palabra: " ) c= raw_input ("Dame la tercer palabra: " ) palabras = [a, b, c] print (palabras) p= raw_input ("desea cambiar una palabra?. Escriba SI o NO: " ) if p == 'SI': k= raw_input("que palabra desea cambiar? " ) if k== a: a= raw_input("Dame la nueva palabra: " ) elif k== b: b= raw_input ("Dame la nueva palabra: " ) elif k== c: c= raw_input ("Dame la nueva palabra: " ) else: print ("La palabra no es correcta") else: print ("No se cambio ninguna palabra") palabras = [a, b, c] print (palabras) z= raw_input("presiona enter")
Menú principal donde te muestra un par de opciones que puede hacer el programa while True: print ("1:SUMA 2:RESTA") print ("3:DIVISION 4:MULTIPLICACION") print ("5:ELEVACION 6:ARREGLO") print ("7:CONTEO 8:SALIR") instruccion= raw_input("Dame el numero de la instruccion que deseas hacer: ") if instruccion== '1': num1= raw_input("Dame el primer numero: ") num2= raw_input("Dame el segundo numero: ") resultado= int(num1) + int(num2) print ("El resultado de la suma es: ", resultado) b=raw_input("presiona enter para finalizar") elif instruccion== '2': num1= raw_input("Dame el primer numero: ") num2= raw_input("Dame el segundo numero: ") resultado= int(num1)-int(num2) print ("El resultado de la suma es: ", resultado) b=raw_input("presiona enter para finalizar") elif instruccion == '3':
32
Portafolio de evidencias de la materia IntĂŠrpretes. JosĂŠ Juan Garcia BĂłrquez. num1= raw_input("Dame el primer numero: ") num2= raw_input("Dame el segundo numero: ") resultado= float(num1)/float(num2) print ("El resultado de la suma es: ", resultado) b=raw_input("presiona enter para finalizar") elif instruccion== '4': num1= raw_input("Dame el primer numero: ") num2= raw_input("Dame el segundo numero: ") resultado= int(num1)*int(num2) print ("El resultado de la suma es: ", resultado) b=raw_input("presiona enter para finalizar") elif instruccion== '5': num1= raw_input("Dame el primer numero: ") num2= raw_input("Dame el segundo numero: ") resultado= int(num1)**int(num2) print ("El resultado de la suma es: ", resultado) b=raw_input("presiona enter para finalizar") elif instruccion== '6': a= raw_input ("Dame la primer palabra: ") b= raw_input ("Dame la segunda palabra: " ) c= raw_input("Dame la tercer palabra: " ) palabras = [a, b, c] print (palabras) p= raw_input ("desea cambiar una palabra?. Escriba SI o NO: " ) if p == 'SI': k= raw_input("que palabra desea cambiar? " ) if k== a: a= raw_input("Dame la nueva palabra: " ) elif k== b: b= raw_input ("Dame la nueva palabra: " ) elif k== c: c= raw_input ("Dame la nueva palabra: " ) else: print ("La palabra no es correcta") else: print ("No se cambio ninguna palabra") palabras = [a, b, c] print (palabras) a= raw_input("Presiona enter") elif instruccion== '7': def conteo (n): if n == 0: print "Despegue!" else: print n conteo(n-1) a=raw_input("presiona enter") conteo (10) b=raw_input("presiona enter para finalizar") elif instruccion == '8':
33
Portafolio de evidencias de la materia Intérpretes. José Juan Garcia Bórquez. b=raw_input("presiona enter para Salir") break else: x= raw_input("Presione ENTER y Elige una opcion correcta.")
34