lunes, 4 de abril de 2016

T1. LA FUNCIÓN RANGE(). HASTA AQUÍ HEMOS LLEGADO.

MUSGO SOBRE LAS PIEDRAS Y HOJARASCA EN EL SOTOBOSQUE DEL MONTE DEL AGUA, NOROESTE DE TENERIFE.

      Esta nueva función de Python nos va a caer simpática. Ya veremos que sí. Se trata de una función integrada que, como su nombre sugiere, determina un rango, delimita un "terreno", un espacio, una porción de algo, por ejemplo, de una lista donde aplicamos una expresión concreta. Precisamente por eso, la función range() incorpora como argumentos un índice de inicio y un índice final que sirve, como nos podemos imaginar, para  encapsular un espacio específico a partir de otro dado, casi lo mismo que consiguen las rebanadas o slices con una string, por ejemplo.


Una FUNCIÓN INTEGRADA puede definirse como aquélla que no requiere ser llamada o invocada desde módulo alguno, en tanto que es accesible por defecto, esto es, que su carga y uso se realiza automáticamente lo que las emparenta con las funciones preconstruidas built-in.
Tengamos en cuenta que la función range() no funciona por sí sola sino que que debe ir asociada a un bucle en for/in para poder desplegar todos sus encantos. Veamos un ejemplo:



En 1. construimos un objeto de tipo de dato list para albergar una colección de números enteros.
Ya en 2. establecemos el bucle for/in para la lista. Hagamos hincapié en que no escribimos la fórmula incluyendo el nombre de la lista, lista_de_números, sino que escribimos directamente la función range(), dado que el incluirla en la fórmula como 'for ítem in lista_de_números in range(5, 10):', por ejemplo, lanzaría una excepción advirtiéndonos de un error de tipo booleano. Esto se debe a que presentada la lista, Python interpreta que el segundo 'in' es un operador de verificación o pertenencia sobre la función range(), indagando sobre sí la lista está presente en range() o no lo que, como podemos deducir, no tiene sentido gramatical.
En 3. Python nos devuelve el resultado iterado, en formato de columna, que muestra la devolución por defecto de la función range() como un ITERADOR o ITERABLE, en tanto que la función permite iterar por todos y cada uno de los elementos que componen la acotación, de principio a fin y de izquierda a derecha. Fijémonos en que al igual que sucede con las rebanadas, el índice de inicio se incluye en el resultado pero el índice final es n-1. Tengámoslo presente.
En 4. añadimos un entero 'z' para que Python nos devuelva el resultado de dos en dos, con lo que hemos obtenido los impares que van del 1 al 10.
En 5. añadimos un entero 'z' para que Python nos devuelva el resultado de dos en dos, con lo que hemos obtenido los pares que van del 10 al 21.
Contamos con una sintaxis singular aprovechando la cualidad de la función range() de recorrer una lista completa establecidos un índice de inicio y otro final, que nos permite realizar una acción sobre todos y cada uno de los ítems de una lista dada. Para hacerlo no tenemos más que pasar como argumento de la función otra función, una de nuestras viejas conocidas. ¿Cuál? La función len() que, repasemos, devuelve la longitud de una colección de datos. Veámoslo en el ejemplo que sigue:


En 1., una vez tenemos la lista, introducimos la sintaxis anteriormente mencionada.
A continuación, en 2., establecemos una llamada a los índices. Al colocar 'item' de la lista estamos diciendo que lo que vayamos a hacer se va a aplicar a todos y a cada uno de los elementos de la lista, gracias a que hemos pasado advirtiendo de ello la función len() como argumento de range().  ¿Y qué es lo que le vamos a hacer a cada uno de estos elementos? Pues  lo que hemos escrito justo a la derecha: un operador de incremento (se utiliza muy a menudo en programación) que sumará 1 a cada ítem, como podemos comprobar en la devolución.
En 3. optamos por incrementar en 10. En 4. por restar o sustraer 1. Y en 5. por multiplicar por 7 cada elemento de nuestra lista. Con este último ejemplo, podríamos construir perfectamente una sencilla tabla de multiplicar.

FLOR DE LA CERRAJA, PLANTA CARACTERÍSTICA DEL BOSQUE HÚMEDO DE TENERIFE.

Fijémonos a continuación en el siguiente ejemplo:



Observemos que en 1., como no nos es posible efectuar la operación de incremento de 1 para todos y cada uno de los ítems, ya que se nos lanza una excepción que nos advierte que el índice que hemos pasado, x, está fuera de rango.
En 2. planteamos la alternativa lógica a la propuesta de sintaxis que hemos visto más arriba con len(), y que pasa por proponer el range() completo, del primero al último de los índices, o lo que es lo mismo:
                                                                      range(índice de inicio, índice final) = len(lista)

Percatémonos de que para que el asunto funcione, le hemos pasado como índice de inicio el número inmediatamente anterior (o menor) que el primero de nuestra lista que, siendo 1, corresponde al 0; mientras que como índice final hemos puesto el último elemento de la lista, 10.
En 3. vemos cómo podemos llevar a cabo la acción seleccionada sobre un grupo de elementos concreto recurriendo al acotamiento que pasamos como argumento de range().


   
      A CONTINUACIÓN MOSTRAMOS UNA TABLA QUE NOS SERÁ SUMAMENTE ÚTIL PARA REALIZAR OPERACIONES ARITMÉTICAS APLICABLES AL TOTAL DE ÍTEMS DE UNA COLECCIÓN.






Es importante tener en cuenta, como acabamos de ver, la dependencia singular, si podemos decirlo así, entre las listas y el bucle for/in para realizar un alto número de operaciones. entraremos en ello con mucha más profundidad cuando tratemos el bucle for/in.
Existe otra forma...mmm...¿cómo decirlo?... más "amable", "elegante" y que consiste en aplicarle a una lista dada un recorrido con la función range() y es recurriendo, de nuevo, a las técnicas de troceado. Pero eso sí, con una rebanada un tanto especial que pasa por incluir dos veces los dos puntos: [x::y], donde x es el índice de inicio e y el valor que se le suma a x dentro de len() de una lista dada. Miremos el ejemplo:



En 1. construimos un bloque de código cuya sintaxis ya conocemos y que consiste en aplicarle a una lista dada un recorrido con la función range() (hubiéramos podido sustituir los datos que pasamos como argumentos por len()) de principio a fin y contando de dos en dos. La aplicación de esta función nos devuelve un resultado iterado de ítems de 1 al 9.
Pero en 2. tenemos que la lista original ha sido transformada en una nueva lista que contiene los mismos valores numéricos que obtuvimos en 1.
En 3. creamos una nueva lista 'k' conformada por strings. Sin embargo, al aplicarle la función iteradora range() obtenemos un resultado similar a 1. ¿Por qué sucede esto? Porque iterará sólo sus índices y no los valores que representan. Para conseguirlo tenemos que escribir:



Finalmente, en 4. observamos cómo obtenemos una nueva lista 'k' con los string que buscábamos.
Terminamos esta entrada dedicada a la función range() aportando unos pocos ejemplos más que nos permitirán comprender mejor las posibilidades y la plasticidad de esta función integrada de Python.





Podríamos necesitar que, en vez de contar hacia a delante, esto es, por ejemplo, de 1 a 10, de menor a mayor, hacerlo al revés, es decir, de 10 a 1, de mayor a menor. Para conseguirlo, tan sólo necesitamos dos cosas: pasar en negativo el primer valor del argumento (nos basta con añadir delante el signo menos, -), que es desde donde empezará a contar, mientras que el segundo lo podemos dejar también con el signo  menos, -, o sin signo dependiendo hasta dónde queramos contar; e incluir la función nativa abs(), de absolute, que como su nombre indica, nos devuelve valores absolutos, sin signo aplicado sobre cada elemento del iterable. Vamos a verlo con ejemplos:



Para finalizar, tengamos presente que la función range() SÓLO admite como argumentos números enteros. No admite ningún otro tipo de dato distinto. De no ser así se lanzará una excepción, un error, desde el intérprete de Python.

AMANECER SOBRE EL TEIDE, CON SU SOMBRA PROYECTÁNDOSE SOBRE EL PICO VIEJO Y TODO A LO LARGO DE LA ISLA.



jueves, 3 de marzo de 2016

T1. SECUENCIAS EN PYTHON. COMO JUGAR A LA OCA.

CASERÍO DE TENO ALTO, MACIZO DE TENO, NOROESTE DE TENERIFE.
Una SECUENCIA es una estructura, serie o colección de datos donde es posible identificarlos y acceder a ellos a través de su índice que, recordemos, es la posición que ocupan cada dato en esa estructura, serie o colección en relación con los demás, de manera individual, esto es, carácter por carácter, o bien a través de rebanadas, slices, cuando queramos identificar y acceder a un grupo (o subgrupo) consecutivo de caracteres dentro de estos mismos datos, haciendo posible operar con ellos. Veamos el siguiente ejemplo:


Existen en Python siete tipos de secuencias: cuerdas (string), cadenas Unicode(que son casi idénticas a nuestras sufridas cadenas con la salvedad de que en su sintaxis, debemos anteponer el prefijo 'u' para señalar que los caracteres literarios que la conforman están supeditados al sistema de codificación Unicode. Por ejemplo, str = u'abc', y que Python adora con auténtica devoción), listas, tuplas, bytearrays, buffers y objetos xrange. Estos tres últimos, no nos interesan por el momento.
Vamos a ver ahora lo que comparten, lo que las secuencias tienen en común y, más adelante, ver luego lo que las diferencia:
  1. No existe límite alguno en cuanto al número o cantidad de elementos o ítems que pueden albergar.
  2. Pueden contener cualquier tipo de objeto como ítems, incluyendo otras secuencias (anidadas). De hecho, una matriz en Python, en síntesis, no es otra cosa que una lista que contiene como elementos n cantidad de listas (sublistas).
  3. No es necesario conocer a priori el tamaño, esto es, el número de elementos que integran la secuencia para poder construirla, lo que permite que se vayan añadiendo elementos a ella de manera progresiva según discurre la ejecución del programa lo que, subsidiariamente, implica una carácter mutable, modificable: la secuencia es mutable porque puede aumentar o disminuir el número de elementos de acuerdo al resultado de la ejecución de los programas.
  4. Soportan algunas funciones nativas de Python:            

  • len(secuencia): devuelve el tamaño o la cantidad de elementos de la secuencia.
  • max(secuencia): devuelve el elemento mayor de la secuencia.
  • min(secuencia): devuelve el elemento menor de la secuencia.


En este ejemplo tenemos una lista 1. compuesta por ocho elementos de tipo string. Al pasarle las funciones nativas de max(secuencia) min(secuencia), nos devuelve, en el primer caso, aquélla que comienza con la letra más próxima a la zeta de acuerdo al orden alfabético, "sauce", en 2.; mientras que en el segundo nos devuelve la más alejada de la zeta o, lo que es lo mismo, la más próxima a la 'a': "abeto".Y es que Python, recordemos, guarda en memoria el orden alfabético estándar, lo que tendrá su incidencia en los distintos métodos de las secuencias.
En 3. tenemos una tupla (tuple) con una serie de números como elementos o ítems integrantes. Un total de ocho. En este caso, como apreciamos en 4., para la función max(secuencia) nos devuelve 123, un tipo de dato int; mientras que para la función min(secuencia) nos devuelve 0.7, un tipo de dato float.
Como podemos comprobar, esto resulta tan sencillo como evidente en secuencias compuestas por datos homogéneos, es decir, que todos ellos, que todos sus elementos o ítems fueran del mismo tipo. ¿Pero qué sucedería si mezcláramos strings y números tal y como se muestra en 5.? Pues tal y como advertimos en 6. se genera un conflicto que Python no puede resolver y lanza una excepción (muestra un error) en el que nos señala, todo angustiado, que son tipos de datos "inordenables" de acuerdo a su diferente naturaleza, que son tipos de datos distintos y, por ende, los califica de error de tipo, TypeError.

VISTA DE LA BALSA DE TREVEJOS, AL FONDO Y EN EL CENTRO, LA BALSA DE AGUA ARTIFICIAL MÁS ALTA DE TENERIFE PARA ACOGER AGUA DE LLUVIA. PINAR DE VILAFLOR, CENTRO SUR DE TENERIFE.
Aparte, las secuencias soportan también dos métodos comunes:
  1. secuencia.index(ítem): devuelve el índice de la primera ocurrencia o aparición del ítem.
  2. secuencia.count(ítem): devuelve el número de veces que aparece el ítem pasado como argumento. Observemos la siguiente comparación: mientras la función len() devuelve el total de ítems de una secuencia, el método secuencia.count(ítem) devuelve el total de veces que aparece un determinado ítem en una secuencia.





En esta última captura podemos apreciar perfectamente como la función len(sentencia) equivale la suma (función sum())de la aplicación del método secuencia.count(ítem) a cada uno de los elementos que componen la secuencia.
Contamos también con otros métodos que podemos pasar a las secuencias devolviéndonos un resultado similar. Algunos de éstos nos los volveremos a encontrar cuando estudiemos los distintos tipos de secuencia. Por el momento, nos conformamos con un aperitivo, para ir abriendo boca como si dijéramos.
  • ELEMENTO DE INTERPOSICIÓN: Para  esto nos basamos en el método str.join(secuencia) que ya estudiamos en el apartado que dedicamos a los métodos de las strings. Este método interpone o intercala un elemento cualquiera pasado como cadena, es decir, entrecomillado, para separar los ítems de una secuencia. Eso sí: dichos ítems o elementos deben ser siempre strings.


  • REBANADAS(SLICES): Refresquemos la memoria. Las rebanadas, slices, consecuencia de aplicar la técnica de slicing, traducible al castellano como "troceado", que así se llama la cosa, pueden imaginarse como "mordiscos" (hay quienes sostienen también que viene a ser como tomar un índice y estirarlo todo lo que queramos: tomamos un índice de inicio, lo estiramos unos cuantos índices intermedios y dejamos de estirar cuando llegamos al índice final que hemos escogido, eso sí, teniendo en cuenta que el índice final se ignora) que le propinamos a una secuencia devolviéndonos trocitos de ella. Como no puede ser de otra manera, los trocitos, rebanadas o slices, son del mismo tipo de dato que la secuencia: las rebanadas de una string son substrings, las rebanadas de una lista son sublistas, las rebanadas de una tupla son subtuplas,.. Fácil de comprender, ¿verdad? Recordemos también que las rebanadas admiten un tercer valor con su sintaxis: secuencia[x:y:z] , donde x e y acotan un trozo concreto, mientras que z determina el cómo se cuenta (de z en z), devolviendo el resultado de la manera en que comentábamos más arriba: una subsecuencia del mismo tipo que su secuencia madre. Por cierto, un valor -z devuelve una subsecuencia vacía.

  

Todas las secuencias son ITERABLES. No olvidemos que esto significa que todos sus ítems o elementos constituyentes pueden recorrerse en orden por un bucle for/in de principio a fin.


Por defecto, cuando pasamos una función print() a un iterable, es decir, a una secuencia, Python nos devuelve el resultado en columna, con los valores resultantes unos encima de otros, como apilados, en el mismo orden en que se se los encuentra en la secuencia. 
En 1. partimos de una secuencia 'a' y aplicamos un bucle o loop for/in para que recorra, no a la secuencia 'a' propiamente dicha sino a una rebanada, a una subsecuencia de 'a', cuyos ítems son 1,3,5,7 y 9. Tengamos en cuenta  que el bucle no se aplica a 'a' sino a una rebanada de 'a', como bien podemos apreciar en el resultado.
Todas las secuencias admiten también el uso del operador in/not in de verificación o pertenencia. Aquí traemos un ejemplo:


CARDONES Y TABAIBAS BAJO CAIDEROS DE AGUA REZUMANTES DE LA LLUVIA EN LAS PAREDES DE LOS BARRANCOS DE IGUESTE DE SAN ANDRÉS, ANAGA, ESTE DE TENERIFE.

No nos olvidemos de que Python se ajusta al case sensitive y distingue entre minúsculas y mayúsculas.
Las secuencias, como ya hemos visto cuando estudiamos el apartado dedicado a  las strings, admiten también la concatenación y la multiplicación. Eso sí, siempre y cuando las secuencias a concatenar y multiplicar sean del mismo tipo.


Efectivamente, en 1. podemos ver como Python no admite concatenación alguna entre dos secuencias de distinto tipo (en realidad no permite ningún tipo de operación, salvo en casos muy concretos, entre secuencias de distinto tipo). En 2. subrayamos simplemente que la estructura de datos set(), al no tratarse de una secuencia, no admite concatenación ni multiplicación.
Finalmente, todas las secuencias admiten el proceso de desempaquetado (unpackage) de sus elementos. Esto del desempaquetado lo estudiaremos más adelante aunque, básicamente, nos quedaremos con la idea de que consiste en extraer todos los elementos de una secuencia, insistimos, todos y asignarles a cada uno de ellos una variable.




Obviamente, tendríamos que contar con tantas variables como elementos contenga la secuencia que queramos desempaquetar. Y qué bien nos viene para saberlo la función len(), ¿eh?

VALLES DEL SUR DE ANAGA, VERTIENTE DE SOTAVENTO, AL ESTE DE TENERIFE, CON EL PICO DE TABORNO PERFILÁNDOSE AL FONDO A LA IZQUIERDA.


sábado, 27 de febrero de 2016

lunes, 1 de febrero de 2016

T3. IDLE DE PYTHON 3

PICO DE TABORNO, UN PITÓN DE INTRUSIÓN VOLCÁNICA EN EL PARQUE RURAL DE ANAGA, CON BREZOS EN PRIMER PLANO, ESTE DE TENERIFE.

      Imaginemos, tal y como nos muestra la captura inferior, que estamos desarrollando un programa y se produce un error (aprovechamos para recordar que en la nomenclatura de Python, a esta clase de evento se la denomina lanzar una excepción, como ya hemos dicho en ocasiones anteriores). Nuestro programa ya cuenta con un tamaño considerable, con un bloque de contenido más o menos grueso, y nos molesta ver ese texto en rojo centrando nuestra atención, más si cabe si sólo estamos codificando o haciendo simples testeos. A pesar de que tras lanzar la excepción Python, muy gentilmente, nos pone a nuestra disposición un prompt libre para continuar con la tortura... No, decididamente, no: No queremos ver ahí ese texto en rojo advirtiéndonos de que somos humanos. ¿Qué podríamos hacer?
Podemos hacer un RESTART, de RE-START, es decir, RE-COMENZAR.



Para hacerlo nos situamos en la barra de menús y hacemos clic en la pestaña shell. Cuando lo hacemos se abre un pequeño cuadro de diálogo y seleccionamos la segunda opción: restart shell (a la derecha se nos muestran atajos de teclado, para quienes gusten de recurrir a ellos).



Y hacemos clic. Ahora ya tenemos nuestro SHELL dividido por una concatenación de símbolos de igualdad, que separa el código antiguo de un nuevo espacio libre donde recomenzar nuestro programa
o comenzar otro distinto. Por cierto que si hacemos clic en la pestaña windows y luego en zoom heights, podemos aumentar en altura (heights) nuestro SHELL. Haciéndolo una segunda vez se nos muestra en pantalla completa.




Por supuesto, podemos hacer un copy-paste de las líneas de código que nos interesen del primer programa e importarlas al nuevo prompt en blanco que nos ofrece restart.



La opción de restart resulta extremadamente útil cuando trabajamos con condicionales  y, por un error  u omisión en la programación, entramos en un bucle infinito. La mejor manera de "romperlo" es, precisamente, a través de restart.
Tenemos la opción de acudir a un atajo de teclado para recobrar la última línea de un código, aquélla que suele ser la causante del error, para recuperarla tras lanzar Python la excepción y modificarla sobre la marcha, a pesar de que sigamos teniendo enfrente el dichoso texto en rojo. Esta combinación de teclas puede ser, según tengamos configurado nuestro teclado, alt + p o alt gr + p.



IMPORTANTE: repite siempre la última línea de texto, aún cuando no se haya lanzado excepción alguna, tantas veces como usemos el atajo:


Dedicaremos más adelante una entrada exclusiva a los atajos de teclado en Python.


      Resumiendo: con restart, empezamos de nuevo a codificar todo nuestro script desde el principio, con lo que dejaremos atrás la excepción si lo que buscamos es un programa limpio, como un escrito sin borrones ni tachaduras. Con el atajo de teclas, alt + p, o bien, alt gr + p,  reescribimos junto al primer prompt vacío la última línea codificada antes de lanzarse la excepción (o la última línea codificada, haya habido o no excepción), permitiéndonos Python efectuar las correcciones pertinentes sobre ella sin necesidad de volver a escribirla toda, y proseguir tranquilamente con nuestro código.





VEREDA ENTRE CAMPOS DE LABOR HACIA EL INTERIOR DE LA LAURISILVA EN ANAGA, ESTE DE TENERIFE.


viernes, 15 de enero de 2016

T3. IDLE DE PYTHON 2

OREJA DE RATÓN (IMAGEN CENTRAL) Y, A LA DERECHA, RETOÑO DE HIERBA CAPITANA, SOBRE LA HOJARASCA DE OTOÑO EN LAS MEDIANÍAS DE LA GUANCHA, NORTE DE TENERIFE.
     Vamos a aprender algunas cosas nuevas sobre el IDLE de Python. Subrayaremos algo que, seguramente, ya conocemos a poco que hayamos trasteado a nuestro aire con los comandos. Es una solución que nos vendrá de perillas cuando el grado de complejidad de nuestros programas vaya en aumento y tengamos que repetir datos y/o líneas de comando a lo largo y a lo ancho de nuestros bloques de código: el copia y pega ("copy and paste").
Cuando queramos copiar una línea de código, total o parcialmente, (recordemos que una línea de código es, en síntesis, y desde la perspectiva de nuestro IDLE, aquéllo que escribimos a la derecha del prompt y que finaliza justo antes del siguiente . No copiemos más de una línea de código, porque incluiremos en el bloque prompts que Python no podrá leer y nos lanzará una excepción: cada copia útil afecta a una sola línea de código o bloque de código, siempre indentado o sangrado en este último caso,  que escribamos a la derecha de un único prompt) y ponerlo en otro prompt distinto, no tenemos más que pasar el cursor por encima, arrastrándolo por el pedazo de línea de código que queramos copiar mientras se sombrea en gris la porción de línea seleccionada, presionando con el botón izquierdo del ratón.





¡Aviso al canto! Como podemos observar claramente en los ejemplos previos, no copiemos el prompt: sólo la línea de código completa o la porción de ella que nos interesa pues, repetimos, de lo contrario Python lanzará un excepción del tipo SyntaxError.
Una vez estemos satisfechos con nuestro subrayado y dispongamos de un prompt vacío donde "pastear", pulsamos el botón derecho para que se nos abra un escueto cuadro de diálogo. Sobre él hacemos clic en copy.



Buscamos a continuación ese prompt vacío junto al cual queremos pastear la copia y hacemos clic con el botón derecho del ratón para que se nos abra nuevamente el mismo cuadro de diálogo.


Finalmente hacemos clic sobre paste y ya está.




Procuremos pegarla bien al prompt porque de lo contrario Python lanzará una nueva excepción, esta vez, advirtiendo de un error de sangrado o indentación, y nuestro gozo en un pozo.


Podemos conseguir un resultado similar acudiendo a la pestaña edit del IDLE.


Para hacerlo sombreamos el texto primero y luego hacemos clic sobre edit para que se nos abra el cuadro de diálogo correspondiente, ya lo sabemos, con el botón izquierdo del ratón.





Con el cuadro de diálogo abierto seleccionamos copy, salimos al SHELL, situamos el cursor junto al prompt que nos interesa y, o bien procedemos como en el caso anterior, o bien volvemos a hacer clic sobre edit, clicamos a continuación sobre paste y salimos de nuevo al SHELL para comprobar el resultado.





Como hemos venido haciendo hasta ahora, poco a poco iremos aprendiendo cosas nuevas de nuestro compañero de fatigas: el IDLE de Python.

TROZO DE LAURISILVA EN EL  BOSQUE DE AGUAGARCÍA, TACORONTE,  CENTRO-ESTE DE TENERIFE


jueves, 14 de enero de 2016