




















Prepara tus exámenes y mejora tus resultados gracias a la gran cantidad de recursos disponibles en Docsity
Gana puntos ayudando a otros estudiantes o consíguelos activando un Plan Premium
Prepara tus exámenes
Prepara tus exámenes y mejora tus resultados gracias a la gran cantidad de recursos disponibles en Docsity
Prepara tus exámenes con los documentos que comparten otros estudiantes como tú en Docsity
Encuentra los documentos específicos para los exámenes de tu universidad
Estudia con lecciones y exámenes resueltos basados en los programas académicos de las mejores universidades
Responde a preguntas de exámenes reales y pon a prueba tu preparación
Consigue puntos base para descargar
Gana puntos ayudando a otros estudiantes o consíguelos activando un Plan Premium
Comunidad
Pide ayuda a la comunidad y resuelve tus dudas de estudio
Ebooks gratuitos
Descarga nuestras guías gratuitas sobre técnicas de estudio, métodos para controlar la ansiedad y consejos para la tesis preparadas por los tutores de Docsity
Ficha 01 [2017] - Fundamentos [Python]Ficha 01 [2017] - Fundamentos [Python]Ficha 01 [2017] - Fundamentos [Python]Ficha 01 [2017] - Fundamentos [Python]Ficha 01 [2017] - Fundamentos [Python]Ficha 01 [2017] - Fundamentos [Python]
Tipo: Guías, Proyectos, Investigaciones
1 / 28
Esta página no es visible en la vista previa
¡No te pierdas las partes importantes!





















1.] Breve referencia histórica: el advenimiento de las computadoras.
Resulta difícil objetar que la segunda mitad del siglo XX (y lo que va del siglo XXI) se vio fuertemente influenciada por la aparición de uno de los inventos más revolucionarios de la historia de la civilización: la computadora^1. Y es que este aparato no sólo revolucionó la vida moderna, sino que en gran medida se ha convertido también en el sostén de la misma: hoy en día las c omputadoras se usan en casi cualquier actividad que admita alguna clase de automatización, y cada vez con más frecuencia también en tareas que otrora eran consideradas "exclusivas" (y distintivas) de la especie humana, como la creación de arte (pictórico, literario, musical), la interpretación de textos y el procesamiento de voz e imágenes, por citar sólo algunos ejemplos comunes.
Por otra parte, la computadora como concepto tecnológico ha sido desde el primer momento de su aparición un invento que no ha parado de mostrar innovaciones y mejoras, al punto que su evolución ha tomado por sorpresa a técnicos, científicos, académicos y empresarios de todas las épocas desde la década del 40 en el siglo XX, provocando muchas frases desafortunadas y errores notables en cuanto a las predicciones efectuadas respecto del futuro del invento.
Como sea, en aquellos lugares del mundo que han alcanzado cierto grado de desarrollo tecnológico resulta casi imposible imaginar la vida cotidiana sin el uso de computadoras. Se utilizan para control de ventas y facturación, para control de stock, para apoyo en diversas áreas de la medicina, en la guerra y la defensa, en la edición de textos, en educación, en el control de comunicaciones, en navegación aérea, espacial, naval y terrestre, en el diseño arquitectónico, en el cálculo, y por supuesto, en el juego...
De hecho, es tal el impacto que las computadoras tienen en esta vida moderna, que incluso llegó a especularse con las más diversas “debacles” tecnológicas cuando estaba llegando a su fin el siglo XX, y se temía que la tradicional forma de representar fechas usando sólo dos dígitos para indicar el año pudiera causar mundialmente problemas enormes (y graves): si una computadora en un banco tomara el año “02” como “1902” y no como “2002”, los resultados en el ámbito de la liquidación de intereses en una cuenta podrían ser inimaginablemente dañinos para la economía mundial, y ni qué hablar del peligro que habría producido un error semejante en el sistema de control de lanzamiento de misiles de una superpotencia, si ésta hubiera tomado el “efecto año 2000” a la ligera. En todo el mundo,
(^1) Todas las referencias históricas que siguen en esta sección, están basadas en los libros que se citan con los
números [1] (capítulo 1), [2] (capítulo 1) y [3] (capítulo 4) de la bibliografía general que aparece al final de esta Ficha.
miles de horas-hombre fueron destinadas a revisar y corregir ese problema durante los años anteriores al 2000, y finalmente puede decirse que todo transcurrió sin problemas.
Las primeras computadoras que pueden llamarse “operativas” aparecieron recién en la década del 40 del siglo XX, y antes de eso sólo existían en concepto, o en forma de máquinas de propósito único que pueden considerarse antecedentes válidos de las computadoras, pero no computadoras en sí mismas. Pero el hecho aparentemente sorprendente es que a pesar del corto tiempo transcurrido desde su aparición como invento aplicable y útil, la computadora ha evolucionado a un ritmo increíble y ha pasado a ser el sustento tecnológico de la vida civilizada... ¡y todo en no más de sesenta años! Esto no es un detalle menor: ningún otro invento ha tenido el ritmo de cambio e innovación que ha tenido la computadora. Si los automóviles (por ejemplo) hubieran innovado al mismo ritmo que las computadoras, hoy nuestros autos serían similares al famoso vehículo volador mostrado en la trilogía de películas de “Volver al Futuro” (quizás exceptuando el “pequeño” detalle de su capacidad para viajar en el tiempo...)
Probablemente la primera persona que propuso el concepto de máquina de cálculo capaz de ser programada para procesar lotes de distintas combinaciones de instrucciones, fue el inglés Charles Babbage [1] [2] [3] en 1821, luego ayudado por su asistente Ada Byron^2 , también inglesa. Ambos dedicaron gran parte de sus vidas al diseño de esa máquina: Babbage diseñó la máquina en sí misma, sobre la base de tecnología de ruedas dentadas, y Byron aportó los elementos relativos a su programación, definiendo conceptos que más de un siglo después se convertirían en cotidianos para todos los programadores del mundo (como el uso de instrucciones repetitivas y subrutinas, que serán oportunamente presentadas en estas notas) La máquina de Babbage y Byron (que Babbage designó como “ Analytical Engine ” o “motor analítico”) era conceptualmente una computadora, pero como suele suceder en casos como estos, Babbage y Byron estaban demasiado adelantados a su época: nunca consiguieron fondos ni apoyo ni comprensión para fabricarla, y ambos murieron sin llegar a verla construida.
En 1890, en ocasión del censo de población de los Estados Unidos de Norteamérica, el ingeniero estadounidense Herman Hollerith [2] diseñó una máquina para procesar los datos del censo en forma más veloz, la cual tomaba los datos desde una serie de tarjetas perforadas (que ya habían sido sugeridas por Babbage para su Analytical Engine). Puede decirse que la máquina de Hollerith fue el primer antecedente que efectivamente llegó a construirse de las computadoras modernas, aunque es notable que el único propósito del mismo era la tabulación de datos obtenidos en forma similar al censo citado: no era posible extender su funcionalidad a otras áreas y problemas (cuando una máquina tiene estas características, se la suele designar como “máquina de propósito específico”). La compañía fundada por Hollerith para el posterior desarrollo de esa máquina y la prestación de sus servicios, originalmente llamada Tabulating Machines Company , se convirtió con el tiempo en la mundialmente famosa International Business Machines , más conocida como IBM.
En 1943, con la Segunda Guerra Mundial en su punto álgido, el matemático inglés Alan Turing [2] [3] estuvo al frente del equipo de criptógrafos y matemáticos ingleses que enfrentaron el problema de romper el sistema de encriptación de mensajes generado por la
(^2) Ada Byron, hija del célebre poeta inglés Lord Byron, era Condesa de Lovelace, y por este motivo suele
aparecer en diversos textos y fuentes de consulta como Ada Lovelace en lugar de Ada Byron.
A finales de la década de 1950 y principios de la de 1960 los tubos al vacío fueron reemplazados por los transistores, lo que permitió abaratar costos y aumentar potencia. La aparición de los circuitos integrados hacia finales de la década del 60 permitió reunir muchos transistores en un solo circuito, abaratando aún más el proceso de fabricación, y permitiendo reducir cada vez más el tamaño (y no sólo el costo) del computador. Esto abrió el camino que llevó a nuestros días: a finales de la década de 1970 aparecieron las primeras computadoras personales ( Apple II e IBM PC ), cuyo costo y tamaño las hacían accesibles para el público promedio... y el resultado está a la vista.
Sin embargo, el hecho que las computadoras hayan ocupado el sitio que ocupan en tan breve plazo, y que evolucionen en la forma vertiginosa que lo hacen, no es en realidad una sorpresa: simplemente se debe al hecho de su propia aplicabilidad general. Las computadoras aparecieron para facilitar tareas de cálculo en ámbitos académicos, científicos y militares, pero muy pronto se vio que podrían usarse también en centenares de otras actividades. Invertir en mejorar el invento valía la pena, y el invento mismo ayudaría a descubrir y definir nuevas áreas de aplicación.
2.] Algoritmos y programas.
En nuestros días las computadoras conviven con nosotros. Donde miremos las encontraremos^4. Es común que haya incluso más de una en cada hogar con nivel de vida promedio. Estamos tan acostumbrados a ellas y tan acostumbrados a usarlas para facilitar tareas diversas, que ni siquiera pensamos en lo que realmente tenemos allí. Si se nos pregunta: ¿qué es una computadora? la mayor parte de las personas del mundo dará una respuesta aproximada, intuitivamente correcta, pero casi nunca exacta y completa. Puede decirse que eso mismo ocurrirá con la mayor parte de los inventos que hoy usamos o vemos a diario, y sin embargo hay una sutil diferencia: sabemos qué es un avión, aunque no sabemos bien cómo funciona ni cómo logra volar. Sabemos qué es un lavarropas, aunque no sabemos bien cómo funciona. Lo mismo se puede decir de los automóviles, las heladeras, los relojes, etc.
Pero con las computadoras es diferente. Podemos darnos cuenta que una computadora es un aparato que puede aplicarse para resolver un problema si se le dan los datos del mismo, de forma que procesará esos datos en forma veloz y confiable y nos entregará los resultados que buscamos. Pero el hecho es que nos servirá para muchos problemas diferentes , incluso de áreas diferentes. La computadora no es una herramienta de propósito único o limitada a una pequeña gama de tareas. Si la proveemos con el programa adecuado, la computadora resolverá cualquier problema. Y aquí está la gran cuestión: podemos ser usuarios de un automóvil sin saber cómo funciona, pues sólo necesitamos que funcione y cumpla su único cometido: trasladarnos donde queremos ir. Pero si queremos que una computadora resuelva los problemas que enfrentamos día a día en nuestro trabajo, o en nuestro ámbito de estudio, o en nuestro hogar, no nos basta con prenderla y limitarnos a verla funcionar. De una forma u otra deberemos cargar en ella los programas adecuados, y a través de esos programas realizar nuestras tareas. Un usuario común de computadoras se limitará a cargar programas ya desarrollados por otras personas. Pero un usuario avanzado, con
(^4) Una referencia complementaria general para esta sección, incluye los libros que aparecen con los números
[1] (capítulo 14) y [4] (capítulo 1) en la bibliografía disponible al final de esta Ficha.
conocimientos de programación, podrá formular sus propios programas, o desarrollarlos para terceros (percibiendo eventualmente una remuneración o pago por ello...) [4].
La tarea de programar un computador no es sencilla, salvo en casos de problemas o ejemplos muy simples. Requiere inteligencia, paciencia, capacidad de resolver problemas, conocimientos técnicos sobre áreas diversas, creatividad, auto superación, autocrítica, y muchas horas de estudio.
El punto de partida para el largo camino en la formación de un programador, es la propia definición del término computadora : se trata de un aparato capaz de ejecutar una serie de órdenes que permiten resolver un problema. La serie de órdenes se designa como programa , y la característica principal del computador es que el programa a ejecutar puede ser cambiado para resolver problemas distintos.
La definición anterior sugiere que la computadora obtendrá los resultados esperados para un problema dado, pero sólo si alguien plantea y carga en ella el programa con los pasos a seguir para resolverlo. En general, el conjunto finito de pasos para resolver un problema recibe el nombre de algoritmo [1] [4]. Si un algoritmo se plantea y escribe de forma que pueda ser cargado en una computadora, entonces tenemos un programa.
En última instancia una computadora es lo que conoce como una “ máquina algorítmica ”, pues su capacidad esencial es la de poder seguir paso a paso un algoritmo dado. Notemos que la tarea del computador es básicamente ejecutar un algoritmo para obtener los resultados pedidos, pero el planteo del algoritmo en forma de programa que resuelve un problema es realizado por una persona, llamada programador. En ese sentido, las computadoras no piensan ni tienen conciencia respecto del problema cuyos resultados están calculando: simplemente están diseñadas para poder ejecutar una orden tras otra, hasta llegar al final del programa.
Los algoritmos entonces, son parte fundamental en el proceso de programación, pero no se encuentran sólo en el mundo de la programación de computadoras: los algoritmos están a nuestro alrededor, y nos permiten llevar a cabo un gran número de tareas cotidianas: encontramos algoritmos en un libro de recetas de cocina, en un manual de instrucciones, o en los gráficos que nos permiten ensamblar un dispositivo cualquiera, por citar algunos ejemplos. También ejecutamos algoritmos cada vez que hacemos un cálculo matemático^5 , o conducimos un automóvil, o grabamos un programa de televisión.
Los algoritmos tienen una serie de propiedades importantes, que son las que permiten su uso generalizado en tareas que pueden descomponerse en pasos menores. Esas propiedades son las siguientes:
i. El conjunto de pasos definido para el algoritmo debe tener un final previsible. Un conjunto de pasos infinito no es un algoritmo, y por lo tanto no es susceptible de ser ejecutado. La obvia conclusión de esta propiedad es que si un algoritmo está bien planteado, se garantiza que quien lo ejecute llegará eventualmente a un punto en el cual se detendrá. Por ejemplo, una secuencia de pasos diseñada para aplicarse sobre cada uno de los números naturales (los números enteros del 1 en adelante), no es un
(^5) De hecho, la palabra algoritmo proviene del nombre del matemático árabe al-Jwarizmi , que en el siglo IX dC
planteó las reglas de las cuatro operaciones aritméticas para el sistema decimal. El conjunto de esas reglas se conoció en Europa como "algoritmia" (después "algoritmo"), y se generalizó para designar a cualquier conjunto de reglas para un problema dado.
procesos ejecutar sobre dichos datos para obtener los resultados. Esto ayuda a poner orden en las ideas iniciales, dejando claros tanto el punto de llegada como el de partida. Si no se tienen claros los datos, se corre el riesgo de plantear procesos que luego no pueden aplicarse simplemente por la ausencia de los datos supuestos. Si no se tienen en claro los resultados, se puede caer en el planteo de un algoritmo que no obtiene lo que se estaba buscando... y en el mundo de los programadores, hay pocas cosas que resulten tan frustrantes e inútiles como la solución adecuada al problema equivocado [4].
Finalmente, el algoritmo debe plantearse de forma que pueda ser asimilado y ejecutado por quien corresponda. Si se diseña un algoritmo para ser ejecutado por una persona, podría bastar con escribirlo en un idioma o lenguaje natural, en forma clara y esquemática, aunque siempre asumiendo que la persona que lo ejecutará entiende las instrucciones primitivas de las que está compuesto. En general, una persona entenderá el algoritmo aunque el mismo tuviera alguna imprecisión o falta de claridad.
Pero si el algoritmo se diseña para ser ejecutado por una máquina, entonces debe ser planteado o escrito en términos que hagan posible que el mismo sea luego transferido a la máquina. Si la máquina es una computadora, el algoritmo debe escribirse usando un lenguaje de programación , generando así lo que se conoce como un programa [1] [4]. Existen muchos lenguajes de programación. Algunos de los más conocidos son C , C++ , Basic , Pascal , Java o Python , siendo este último el que usaremos a lo largo del curso.
Un lenguaje de programación es un conjunto de símbolos, palabras y reglas para combinar esos símbolos y palabras de forma muy precisa y detallada. Los lenguajes de programación prevén un cierto conjunto mínimo de palabras válidas (llamadas “ palabras reservadas ”) y un cierto conjunto de símbolos para operaciones generalmente matemáticas y lógicas (llamados “ operadores ”). Pero no cualquier combinación de esos operadores y palabras reservadas resulta en una orden válida para el lenguaje, de la misma forma que no cualquier combinación de palabras castellanas resulta en una frase comprensible en español. Los operadores y palabras reservadas deben combinarse siguiendo reglas específicas y muy puntuales. El conjunto de esas reglas se conoce como la sintaxis del lenguaje. Por ejemplo, en el lenguaje Python se puede preguntar si una proposición dada es cierta o falsa por medio de una instrucción condicional que se forma con las palabras reservadas if y else , junto con algunos signos especiales los dos puntos ( : ). Para escribir la condición a evaluar se pueden usar operadores como <, >, >=, etc. Pero la sintaxis o conjunto del reglas del lenguaje exige que esas palabras, signos especiales y operadores se escriban de una forma determinada para que la instrucción condicional sea válida. Una forma válida de escribirla sería:
if x >= 10:
else:
Sin embargo, la siguiente combinación de las mismas palabras, símbolos y operadores (que originalmente estaban en color azul en el modelo anterior) es de sintaxis totalmente incorrecta en Python (¡y muy posiblemente también en cualquier otro lenguaje!):
else x: = 10 > : if
En definitiva, para que un computador pueda ser usado para resolver un problema, los pasos a seguir se ven en el siguiente esquema:
Figura 3: Pasos para resolver un problema mediante un computador.
Los pasos 1 y 2 del esquema anterior resultan esenciales para seguir adelante en el proceso. "Entender el problema" (es decir, lograr una "representación del problema") es básicamente saber identificar los objetivos (o resultados ) a cumplir, junto a los datos de los cuales se parte, y ser capaz de plantear una estrategia general de resolución en la que se indiquen los procesos básicos a realizar para llegar a los resultados partiendo de los datos. En esta etapa de comprensión inicial, esa estrategia de planteo no requiere mayor nivel de detalle: basta con que se pueda simplemente comunicar en forma verbal una línea de acción general. Si bien puede parecer una etapa simple y obvia, los hechos muestran que en realidad se trata del punto más complicado y difuso en el proceso de resolver un problema. Si el problema no es de solución trivial, quien plantea el problema debe ser capaz de intuir una línea de acción que lo conduzca, eventualmente, a una solución correcta. Mientras más experimentada en resolución de problemas es la persona, mayor es la probabilidad que la línea de acción intuida sea correcta. Sin embargo, no hay garantías: quien intenta resolver el problema sigue rutas lógicas que su experiencia indica pueden ser correctas, pero el éxito no es seguro. A menudo los caminos elegidos llevan a puntos muertos, o terminan alejándose de la solución buscada. Pues bien: el conjunto de estrategias, procesos y caminos lógicos que una persona intuye que puede servir para dar con una solución a un problema no trivial (en cualquier campo o disciplina), se conoce con el nombre de heurístico (del griego heuriskin : lo que sirve para resolver), o más general, como método heurístico.
Es obvio que una persona con escasos o nulos conocimientos en el área del problema, difícilmente podrá encontrar una solución al mismo. Pero si los conocimientos se suponen dados, aun así los hechos muestran que encontrar una "estrategia resolvente" para un problema es una tarea exigente. Como vimos en la Figura 3, todo el trabajo que un programador debe realizar comienza con la inspiración de un heurístico: la intuición de una estrategia resolvente. Si en este punto falla o no logra ni siquiera comenzar, no podrá dar un solo paso más y la computadora no le servirá de mucho.
Es en el segundo paso, con el planteo del algoritmo, donde la estrategia elegida debe ser detallada con el máximo y exhaustivo rigor lógico. En esta etapa, cada paso, cada condición, cada rama lógica del proceso, debe ser expresada sin ambigüedad. Toda la secuencia de acciones a cumplir para llegar a los objetivos planteados debe quedar evidenciada en forma clara y terminante. Normalmente, se emplean en esta etapa una serie de símbolos para facilitar la tarea de mostrar el algoritmo, formando lo que se designa como un diagrama de flujo junto a otros diagramas específicos. Cabe aclarar sin embargo, que hasta aquí lo importante es plantear en forma rigurosa la lógica del algoritmo, y no los detalles sintácticos
Entender el problema
Especificar un algoritmo
Desarrollar un programa
Verificar y ejecutar el programa
ejemplo de lenguaje mixto podemos citar a Java. Y en nuestro caso más próximo, tenemos a Python que finalmente es un ejemplo de lenguaje interpretado.
A pesar de todo lo dicho, cabe aclarar que por razones de comodidad y de uso y costumbre entre los programadores, tanto los errores de sintaxis detectados e informados por un compilador como los detectados e informados por un intérprete son designados indistintamente como errores de compilación : es decir, errores en la sintaxis de un programa fuente que impiden que ese programa comience a ejecutarse y/o finalice en forma completa (si está siendo ejecutado por un intérprete ).
Como vimos, un programa no es otra cosa que un algoritmo escrito en un lenguaje de programación. Conocer las características del lenguaje es un paso necesario, pero no suficiente, para poder escribir un programa: alguien debe plantear antes un algoritmo que resuelva el problema dado. En todo caso, la computadora (a través del compilador o el intérprete) ayuda a encontrar errores sintácticos (pues si un símbolo falta o está mal usado, el compilador o el intérprete avisa del error), pero no puede ayudar con los métodos heurísticos para llegar a un algoritmo.
Cuando el programa ha sido escrito y verificado en cuanto a sus errores de compilación, el mismo puede ser cargado en la computadora y finalmente en el paso 4 se procede a solicitar a la computadora que lo ejecute (es decir, que lleve a cabo las tareas indicadas en cada instrucción u orden del programa). Si el programa está bien escrito y su lógica subyacente es correcta, puede confiarse en que los resultados obtenidos por el ordenador serán a su vez correctos. Si el programa contiene errores de lógica, aquí debe realizarse un proceso de revisión (o verificación) y eventualmente repetir los pasos desde el 2 hasta el 4. Veremos más adelante numerosos ejemplos de aplicación de este proceso.
Para terminar esta introducción, debe notarse que el motivo básico por el cual una persona que sabe plantear un algoritmo recurre a un computador para ejecutarlo, es la gran velocidad de trabajo de la máquina. Nadie duda, por ejemplo, que un ingeniero sabe hacer cálculos de estructuras, pero con una computadora adecuadamente programada podrá hacerlo mucho más rápido.
3.] Fundamentos de representación de información en sistema binario.
Una computadora sólo sirve si posee un programa cargado al que pueda interpretar y ejecutar instrucción por instrucción. Además del propio programa, deben estar cargados en el interior de la computadora los datos que ese programa necesitará, y del mismo modo la computadora almacenará los resultados que vaya obteniendo.
Esto implica que una computadora de alguna forma es capaz de representar y retener información dentro de sí. En ese sentido, se llama memoria al dispositivo interno del computador en el cual se almacena esa información y básicamente, la memoria puede considerarse como una gran tabla compuesta por celdas individuales llamadas bytes , de modo que cada byte puede representar información usando el sistema de numeración binario basado en estados eléctricos.
Para entender lo anterior, digamos que esencialmente una computadora sólo puede codificar y decodificar información mediante estados eléctricos. Cada celda o byte de memoria, está compuesto a su vez por un conjunto de ocho terminadores eléctricos, que reciben cada uno el nombre de bit (acrónimo del inglés binary digit o dígito binario ). En la
práctica, se suele reducir la idea de bit a la de un componente que en un momento dado puede estar encendido (o con valor 1 ) o bien puede estar apagado (o con valor 0 ) [1]. Por este motivo, decimos que una computadora sólo puede usar e interpretar el sistema de numeración binario (o de base 2 ), que consta únicamente de los dígitos 0 y 1.
En base a los dos únicos dígitos 0 y 1, la computadora debe codificar cualquier tipo de información que se requiera. Si se trata de representar números enteros, está claro que los dígitos 0 y 1 del sistema binario servirán sin problemas para representar el 0 y el 1 del sistema de numeración decimal (o de base 10 ). Por lo tanto, un único bit podría usarse para representar al 0 o al 1 en la memoria. Pero si se quiere representar al número 2 o al 3, está claro que necesitaremos más bits y combinar sus valores [5].
Dado que un bit permite representar dos estados posibles (esto es: 2^1 = 2 estados), entonces dos bits juntos pueden representar 2^2 = 4 estados. Con eso alcanzaría para representar en binario a los dígitos del 0 al 3 de la base 10:
Figura 6: Representación en binario de los primeros cuatro números decimales.
Dígito decimal Representación binaria (precisión: 2 bits)
0 00 1 01 2 10 3 11
La cantidad de bits usada para representar en binario un valor cualquiera, se conoce como la precisión de la representación. En la tabla anterior, se representaron los cuatro primeros dígitos decimales, con precisión de dos bits.
Puede verse claramente por qué motivo en la memoria de un computador, los bits se agrupan tomados de a ocho para formar bytes: una precisión de 8 bits permitiría representar 28 = 256 números enteros diferentes en un único byte. Por lo tanto, si a modo de ejemplo asumimos que sólo se representarán números positivos , entonces un único byte puede usarse para representar números enteros en el intervalo [0, 255] (lo cual equivale a 256 números, incluido el 0). Si se quiere representar números enteros positivos mayores a 255, entonces la computadora agrupa dos o más bytes , e interpreta el contenido agrupado para obtener un único valor. Así, usando dos bytes agrupados, se tiene un total de 16 bits que implican 2^16 = 65536 números enteros positivos diferentes, en el intervalo [0, 65535].
Y así continúa: mientras mayor sea la magnitud del número que se quiere representar, mayor será la cantidad de bits que requerirá para su representación interna en un computador, y mayor será entonces la cantidad de bytes que ocupará. Como los números enteros negativos también se representan en binario, usando una técnica designada como complemento a dos , entonces un único byte normalmente puede almacenar tanto negativos como positivos, en precisión de 8 bits, pero esto (y otros detalles técnicos) hace que el rango de valores ahora sea el del intervalo [-128, 127] (o sea, 256 números desde el -128 hasta el 127, incluyendo al 0). Si se usan dos bytes, entonces el rango de valores enteros es [-32768, 32767] (o sea, 65536 números, desde el -32768 hasta el 32767 incluido el 0). Usando 4 bytes, se tienen 32 bits de precisión, con 2^32 = 4294967296 valores enteros diferentes (más de 4 mil millones de números) en el intervalo [-2147483648, 2147483647] (que incluye al 0) si se admiten negativos.
En el gráfico (que es sólo una representación libre de la idea de memoria como tabla formada por casilleros), se supone que la variable x1 contiene el valor 7, y del mismo modo el resto de las variables del cuadro contiene algún valor. El nombre de cada variable es elegido por el programador, de acuerdo a ciertas reglas que se verán más adelante.
Está claro que lo que realmente se almacena en cada variable es la representación binaria de cada valor, pero aquí por razones se simplificación mostramos los valores tal como los entiende una persona. La cantidad de bytes que se usó para graficar a cada variable está en correspondencia con el tipo de valor representado y también de acuerdo a la forma de trabajo de Python : en este lenguaje, una variable que almacene un número entero ocupará automáticamente la cantidad de bytes que requiera para poder representar ese valor. Por lo tanto, la variable x1 sólo ocupará un byte (ya que el número 7 representado en binario puede almacenarse sin problemas en un único byte). Pero la variable x3 , que también almacena un número entero, en este caso ocupa dos bytes ya que el valor 1358 en binario requiere al menos de dos bytes para poder ser representado.
En la misma gráfica, la variable x2 se representó con ocho bytes. El motivo es que x contiene el valor 23.67 que no es entero, sino de coma flotante. En Python, todos los números de coma flotante (o reales ) se representan con ocho bytes de precisión, sin importar la magnitud del número.
Finalmente, la variable c , que contiene un único caracter (el signo @) se graficó con dos bytes. El motivo: Python utiliza el estándar Unicode para representar caracteres. Por la misma razón, la variable nom en la gráfica ocupa ocho bytes: dos por cada caracter de la palabra "Juan".
Para darle un valor a una variable en Python (o para cambiar el valor de la misma)^6 se usa la instrucción de asignación , que consiste en escribir el nombre de la variable, seguido del signo igual y luego el valor que se quiere asignar. El signo igual (=) se designa como operador de asignación [6]. Ejemplo:
x1 = 7
La instrucción anterior, internamente, convierte el valor 7 a su representación binaria, y almacena ese patrón de bits en la dirección de memoria en la que esté ubicada la variable x1 , manejando automáticamente Python la cantidad de bytes que necesitará.
La clase de valores que una variable puede contener en un momento dado, se llama tipo de dato. Los lenguajes de programación proveen varios tipos de datos estándar para manejar variables. Así, en el lenguaje Python existen al menos tres tipos elementales que permiten manejar números enteros, números en coma flotante, y valores lógicos ( True y False ). Además, Python permite manejar cadenas de caracteres y muchos otros tipos de datos predefinidos. El cuadro de la Figura 8 muestra los nombres y algunas otras características de los tipos de datos que hemos citado (otros tipos serán estudiados oportunamente).
En muchos lenguajes (tales como C , C++ o Java ) no se puede utilizar una variable en un programa si la misma no fue convenientemente declarada en ese programa. En esos lenguajes, la declaración de una variable se hace mediante la llamada instrucción
(^6) La fuente de consulta general y más recomendable para el uso y aplicación del lenguaje Python, son sus
propios manuales, tutoriales y documentación publicados en forma oficial por la Python Software Foundation. Esa documentación está designada con el número [5] en la bibliografía que aparece al final de esta Ficha.
declarativa , que implica indicar el nombre o identificador de la variable, e indicar a qué tipo de dato pertenece esa variable. Los lenguajes de programación que obligan a declarar una variable antes de poder usarla, comprueban que los valores asignados sean del tipo correcto y lanzan un error en caso de no serlo. En general, estos lenguajes se suelen denominar lenguajes de tipado estático.
Figura 8: Tabla de tipos de datos elementales en Python (sólo los más comunes).
Tipo (o Clase) Descripción^ Bytes por cada variable^ Rango bool valores lógicos 1 [False, True] int números enteros dinámico^7 ilimitado^8 float números reales 8 hasta 15 decimales str cadenas de caracteres 2 * cantidad de caracteres Unicode
Por su parte, Python y otros lenguajes (como Perl o Lisp ) son lenguajes de tipado dinámico : esto significa que una misma variable puede recibir y almacenar valores de tipos diferentes durante la ejecución de un programa, y por lo tanto las variables no deben declararse en base a un tipo específico prefijado antes de ser usadas.
A diferencia de los lenguajes de tipado estático, una variable en Python se define (o sea, se aloja en memoria) en el momento en que se le asigna un valor (de cualquier tipo) por primera vez, y el tipo inicialmente asumido para esa variable es el que corresponda al valor que se le asignó. Por ejemplo, el siguiente esquema define cuatro variables en Python:
a = 14 b = 23. c = 'Python' d = True
La variable a se define inicialmente como de tipo entero ( int ), y toma el valor 14. Respectivamente, las variables b , c y d se definen como flotante ( float ), cadena de caracteres ( str ) y lógica ( bool ). Note en los cuatro casos, el uso del operador de asignación (el signo igual =) para llevar a cabo la asignación de cada valor en la variable respectiva. Note también que en cada una de las cuatro instrucciones se usó directamente el operador de asignación y el lenguaje deduce el tipo y el tamaño en bytes de la variable de acuerdo al valor asignado. El tipo es implícito y en ningún caso se requiere usar el propio nombre de cada tipo ( int , float , str , bool o el que fuese).
Si se trata de asignar un número entero, es suficiente con escribir ese número luego del operador de asignación, eventualmente precedido de un signo menos. Si el número es de coma flotante, recuerde usar el punto (y no la coma ) como separador entre la parte entera y la parte decimal. Si quiere asignar una cadena de caracteres o un caracter único a una variable, encierre la cadena o el único caracter entre comillas dobles o entre apóstrofos (o comillas simples) como se hizo en el ejemplo. Como veremos, el uso de comillas dobles o simples es indistinto en Python , siempre que se mantenga consistente: si abrió con comillas dobles, debe cerrar con comillas dobles, pero si abrió con apóstrofos, debe cerrar con apóstrofos. Y finalmente, si desea asignar un valor lógico (de tipo bool ) a una variable, debe
(^7) Es decir, la cantidad de bytes que ocupa una variable de tipo int se calcula y asocia en el momento en que se
necesita. (^8) En este contexto, "ilimitado" significa que no hay un límite teórico al rango de valores enteros que se pueden
representar en Python, pero hay un límite práctico que es la capacidad de memoria disponible.
El tamaño en bytes de una variable es automáticamente ajustado por Python de acuerdo al valor que se asigna en la misma, sin que ese detalle deba preocupar al programador. Así, si se trabaja con números enteros y se asignan a una variable valores como 4, 2345 o 54763, Python adecuará el tamaño de la variable usada a uno, dos o cuatro bytes según sea el caso, y así en forma similar con otros valores que requieran mayor espacio o con otros tipos de datos.
Un hecho importante derivado de la forma de trabajo de la instrucción de asignación, es que cuando se asigna un valor a una variable, esta asume el nuevo valor, y pierde cualquier valor anterior que hubiera contenido. Por ejemplo, considérese el siguiente segmento de programa: a = 2 a = 4
En este caso, se comienza asignando el valor 2 a la variable a , pero inmediatamente se asigna el 4 en la misma variable. El valor final de a luego de estas dos instrucciones, es 4, y el 2 originalmente asignado se pierde. Lo mismo ocurre con cualquier otra variable, sea cual sea el tipo de la misma.
En Python una variable puede cambiar dinámicamente de tipo, pero lo que no se puede hacer es intentar usar una variable sin haberle asignado previamente un valor inicial alguna vez. El siguiente ejemplo provocará un error (suponiendo que la variable b no haya sido usada nunca antes):
a = 34 print('Valor de a: ', a)
print("Valor de b: ", b)
En algunas situaciones, puede esperarse que una variable sea asignada con el valor None (que implícitamente equivale a un False ), indicando que la variable es válida pero carece de valor en ese momento:
r = None print('Valor actual de r: ', r)
Los siguientes ejemplos son válidos para ilustrar algunos elementos básicos en cuando a gestión de variables y las posibilidades de la instrucción de asignación (los números a la izquierda de cada línea se usan para poder hacer referencia a cada ejemplo, y no forman parte de un programa en Python):
Figura 9: Ejemplos de asignaciones de variables en Python.
1.) c = '+' 2.) a = c 3.) a = 'c' 4.) b = 'Juan' 5.) d = b 6.) d = 'b'
c (^) "+" a (^) "+" a "c" b 1
"Juan" d 1
"Juan" d 1
"b"
Estado de cada variable luego de cada asignación
En la línea 1.) se asigna el caracter "+" a la variable c , y luego en la línea 2.) se asigna la variable c en la variable a. Esto significa que la variable a queda valiendo lo mismo que la variable c (es decir, ambas contienen ahora el signo "+")^9. Observar la diferencia con lo hecho en la línea 3.), en donde se asigna a la variable a el caracter "c" (y no el contenido de la variable c ). En la línea 4.) se asigna la cadena "Juan" a la variable b , y en la línea 5.) se asigna el contenido de la variable b en la variable d (de nuevo, ambas quedan valiendo lo mismo: la cadena "Juan"). En la línea 6.) se está asignando literalmente la cadena "b" a la variable d , por lo que las líneas 5.) y 6.) no son equivalentes…
Para finalizar esta sección, recordemos que el nombre o identificador de una variable (y en general, el identificador de cualquier elemento creado por el programador) es elegido por el propio programador, pero para ello deben seguirse ciertas reglas básicas, que indicamos a continuación [6]:
El nombre o identificador de una variable en Python, sólo puede contener letras del alfabeto inglés (mayúsculas y/o minúsculas, o también dígitos (0 al 9), o también el guion bajo ( _ ) (también llamado guion de subrayado). El nombre de una variable no debe comenzar con un dígito. Las palabras reservadas del lenguaje Python no pueden usarse como nombres de variables. El nombre de una variable puede contener cualquier cantidad de caracteres de longitud. Recordar que Python es case sensitive : Python hace diferencia entre minúsculas y mayúsculas, por lo que toma como diferentes a dos nombres de variables que no sean exactamente iguales. El identificador sueldo no es igual al identificador Sueldo y Python tomará a ambos como dos variables diferentes.
Hacemos notar que estas reglas son las más elementales, y son las que fija la versión Python
Figura 10: Ejemplos de identificadores de variables válidos en Python 3.
Identificador Observaciones n1 Válido en Python 2 y Python 3 nombre_2 Válido en Python 2 y Python 3 sueldo_anterior Válido en Python 2 y Python 3 x123 Válido en Python 2 y Python 3 año Válido en Python 3 – No válido en Python 2 por el uso de la ñ (no inglesa) número Válido en Python 3 – No válido en Python 2 por el uso de la ú (no valen acentos en inglés)
(^9) Cuando se asigna un caracter o una cadena de caracteres a una variable, las comillas (simples o dobles)
usadas para delimitar al caracter o a la cadena, no quedan almacenados en la variable. En la gráfica se muestran las comillas como si estuviesen contenidas en las variables, pero sólo por razones de claridad. (^10) En definitiva, en Python 2 un identificador se forma usando caracteres ASCII que representen letras, guiones
bajos o dígitos, pero en Python 3 se aceptan también caracteres Unicode ( no – ASCII ), para dar cabida a símbolos propios de otros idiomas diferentes del inglés.
usuario cargue, será retornado por la función input() en forma de cadenas de caracteres (con el salto de línea final removido) [6]. Así, una instrucción de la forma:
nom = input('Ingrese su nombre: ')
provocará que se muestre en consola el mensaje " Ingrese su nombre: ", con el cursor del prompt parpadeando a continuación y dejando el programa en estado de espera hasta que se el usuario ingrese datos y presione < Enter >. Si al ejecutar esta instrucción, por ejemplo, el usuario escribe la palabra " Ana " (sin las comillas) y presiona < Enter >, la variable nom quedará valiendo la cadena " Ana " (de nuevo, sin las comillas).
Si se quiere cargar por teclado un número entero o un número en coma flotante, deben usarse funciones predefinidas del lenguaje que hagan la conversión de cadena a número. Para eso, Python provee al menos dos de ellas:
int(cadena) : retorna el número entero representado por la cadena tomada como parámetro (escrita entre los paréntesis). float(cadena) : retorna el número en coma flotante representado por la cadena tomada como parámetro.
En ambos casos, si la cadena tomada como parámetro no representa un número válido que pueda convertirse, se producirá un error en tiempo de ejecución y el programa se interrumpirá.
Por lo tanto, las siguientes expresiones permiten en Python cargar por teclado un número entero en la variable n (la primera instrucción) y un número en coma flotante en la variable x (la segunda):
n = int(input('Ingrese un valor entero: ')) x = float(input('Ingrese un valor en coma flotante: '))
Note que en ambas líneas de este ejemplo, se han usado las comillas simples o apóstrofos para encerrar las cadenas de caracteres. Recuerde que en Python es indistinto el uso de las comillas dobles o las simples para hacer esto, siempre que se mantenga consistente (abrir y cerrar con el mismo tipo de comilla). Las mismas dos instrucciones podrían haber sido escritas así:
n = int(input("Ingrese un valor entero: ") ) x = float(input("Ingrese un valor en coma flotante: "))
O incluso combinando así:
n = int(input("Ingrese un valor entero: ") ) x = float(input('Ingrese un valor en coma flotante: '))
Tenga en cuenta que en todo lenguaje existen convenciones de trabajo y consejos de buenas prácticas, y Python no es la excepción. En ese sentido, indicamos que lo más común es que se usen comillas simples para delimitar caracteres o cadenas de caracteres, y esa es la convención que hemos tratado de mantener a lo largo de esta ficha de estudio.
Puede verse que la posibilidad de hacer carga por teclado mientras el programa se ejecuta, permite mayor generalidad en el planteo de un programa [4]. A modo de ejemplo, suponga que se quiere desarrollar un pequeño programa en Python para sumar los números contenidos en dos variables. Un primer intento podría ser el siguiente:
a = 5
b = 3 c = a + b print('La suma es: ', c)
El pequeño programa anterior funciona… pero podemos darnos cuenta rápidamente que así planteado es muy poco útil, pues indefectiblemente el resultado mostrado en pantalla será 8... El programa tiene muy poca flexibilidad debido a que el valor inicial de la variable a es siempre 5 y el de b es siempre 3. Lo ideal sería que mientras el programa se ejecuta , pueda pedir que el usuario ingrese por teclado un valor para la variable a , luego otro para b , y que luego se haga la suma (en forma similar a como permite hacerlo una calculadora...) Y eso es justamente lo que permite hacer la función input(). El siguiente esquema muestra la forma correcta de hacerlo:
a = int(input('Primer valor: ')) b = int(input('Segundo valor: ')) c = a + b print('La suma es: ', c)
Observar que de esta forma, cada vez que se ejecuta el programa se puede cargar un valor distinto en cada variable, y obtener diferentes resultados sin tener que modificar y volver a ejecutar el programa.
6.] Operadores aritméticos en Python.
Hemos visto que siempre se puede asignar en una variable el resultado de una expresión. Una expresión es una fórmula en la cual se usan operadores (como suma o resta) sobre diversas variables y constantes (que reciben el nombre de operandos de la expresión). Si el resultado de la expresión es un número, entonces la expresión se dice expresión aritmética. El siguiente es un ejemplo de una expresión aritmética en Python:
num1 = 10 num2 = 7 suma = num1 + num
En la última línea se está asignando en la variable suma el resultado de la expresión num1 + num2 y obviamente la variable suma quedará valiendo 17. Note que en una asignación primero se evalúa cualquier expresión que se encuentre a la derecha del signo =, y luego se asigna el resultado obtenido en la variable que esté a la izquierda del signo =. La siguiente tabla muestra los principales operadores aritméticos del lenguaje Python (volveremos más adelante con un estudio más detallado sobre la aplicación de estos operadores) [6]:
Figura 12: Tabla de operadores aritméticos básicos en Python.
Operador Significado Ejemplo de uso