Kitabı oku: «El gran libro de Python», sayfa 5

Yazı tipi:

Instrucciones simples

Según la definición anterior, una línea lógica constituida por una expresión es una instrucción simple. Este, evidentemente, es el único caso en que una instrucción es también una expresión. El resultado de esta instrucción no puede ser guardado; por este motivo, una expresión se utiliza como instrucción solo en dos casos. El primero es cuando se utiliza el modo interactivo, puesto que, aunque el resultado de la expresión no sea guardado, este se escribe en la salida estándar y se puede comprobar visualmente:


La otra situación es la de las llamadas funciones y métodos que no devuelven explícitamente un objeto, puesto que en estos casos interesa solo que se ejecuten las acciones y no se obtiene ningún resultado que guardar:


El resto de las instrucciones simples no son expresiones y, por tanto, no pueden ser asignadas a una etiqueta. Veamos una parte a continuación.

La asignación

La asignación es una instrucción simple que asigna el objeto generado por la expresión a la derecha del signo = a la etiqueta situada a la izquierda del mismo signo:


Es posible asignar el mismo objeto a distintas etiquetas en una única instrucción:


y esta resulta equivalente a las secuencias de las asignaciones individuales:


También es posible realizar asignaciones en paralelo, mediante el desempaquetado:


Hablaremos en detalle del desempaquetado en el capítulo siguiente, en la sección titulada Operaciones y funciones integradas utilizables con los objetos iterables.

La instrucción pass

La palabra clave pass es una instrucción simple que no ejecuta nada. Cuando se localiza, se omite y la ejecución continúa con la instrucción siguiente:



La instrucción del

La instrucción del elimina una o más etiquetas:


La instrucción return

La instrucción return, que se utiliza solo en el interior de una función, sirve para devolver de forma explícita al que realiza la llamada el resultado de la función:


Si una función no devuelve explícitamente un objeto al que realiza la llamada, se devuelve implícitamente el objeto None, la única instancia del tipo NoneType:


La instrucción import

La instrucción import sirve para importar módulos:



Veremos de manera detallada la instrucción import en el tercer capítulo, cuando hablemos de los módulos.

La instrucción from

La instrucción from se utiliza para importar atributos de un módulo:


La instrucción from tiene distintas variantes, que veremos en el Capítulo 4.

La instrucción assert

La instrucción assert genera una excepción del tipo AssertionError si su expresión de prueba se valora como False; si no, no hace nada:


Veremos más detalladamente esta instrucción en el Capítulo 5, cuando hablemos de las excepciones.

Instrucciones compuestas

La instrucción compuesta está formada por una o más palabras clave, denominadas cláusulas, cada una de las cuales tiene asociada una suite de instrucciones. Las cláusulas terminan con el signo de dos puntos, después del cual empieza la suite:


Como ya sabemos, generalmente la suite se escribe en un bloque de código indentado, con una instrucción por línea:


Las cláusulas tienen todas el mismo nivel de indentación, como podemos observar en el siguiente ejemplo, que muestra la instrucción if y su cláusula else:


En esta sección mostraremos el modo en que se utilizan las tres principales instrucciones compuestas: if, for y while.

La instrucción if

En Python existen dos herramientas que permiten emprender distintas acciones basándose en el resultado de una prueba de la verdad. La primera es la expresión condicional, de la cual ya hemos hablado, mientras que la segunda es la instrucción compuesta if, con las cláusulas elif y else. Su forma general es la siguiente:


y este es un ejemplo de su uso:


En Python no existe una instrucción para las elecciones múltiples parecida a la switchcase típica de otros lenguajes (ver PEP-0275 y PEP-3103). Esta elección se debe al hecho de que es posible obtener de manera obvia el mismo resultado con la instrucción if y, como ya sabemos, “there should be one - and preferably only one - obvious way to do it”.

Es posible obtener la opción -case también con los diccionarios, probablemente de manera menos intuitiva respecto a la correspondiente codificación con la instrucción if:


La instrucción for

La instrucción for permite ejecutar iteraciones:


Los elementos del objeto iterable también pueden ser desempaquetados:


Cuando en el interior de un bucle for se ejecuta la instrucción simple continue, el resto de instrucciones del bloque son saltadas y la ejecución se retoma a partir de la línea que contiene la palabra clave for:


La instrucción simple break termina la ejecución del bucle for:


También es posible utilizar la cláusula else, la cual se ejecuta si sale del bucle sin encontrar la instrucción break:


En la sección Objetos iterables, iteraciones y contexto de iteración, al final de este capítulo, describiremos detalladamente los mecanismos en que se basa el protocolo de iteración.

La instrucción while

La instrucción while permite ejecutar bucles infinitos:


Podemos utilizar continue, break y la cláusula else del mismo modo en que se utiliza la instrucción for.

Los módulos como contenedores de instrucciones

Acabamos de ver que las expresiones están incluidas en las instrucciones. Estas, a su vez, están incluidas en el interior de módulos Python. Los módulos Python son archivos que contienen ninguna (un archivo vacío, el módulo más pequeño...) o alguna instrucción Python. Estos se importan mediante la instrucción import y, a su vez, pueden importar otros módulos.

Para poder ser importado, un módulo Python debe ser necesariamente un archivo con sufijo .py, pero cuando se escribe la instrucción import el nombre del módulo se escribe sin sufijo. Consideremos, por ejemplo, el siguiente archivo foo:


Podemos ejecutarlo:


pero no importarlo:


Cuando importamos un módulo, este se ejecuta:


La instrucción from permite copiar los atributos de un módulo, es decir, las etiquetas definidas en su interior:


Al inicio de esta sección, hemos indicado que las instrucciones están incluidas en los módulos, en cuyo caso debemos preguntarnos en qué módulo se encuentran las ejecutadas en modo interactivo. La etiqueta global _ _name_ _ no da la respuesta. Esta, de hecho, se refiere al nombre del módulo en el cual se utiliza:


Por tanto el código ejecutado en modo interactivo reside en el interior de un módulo denominado _ _main_ _:



Un archivo mymodule.py, cuando se ejecuta directamente desde la línea de comandos, también se carga en memoria con el nombre _ _main_ _ así como con el nombre mymodule. Consideremos, por ejemplo, el siguiente archivo mymodule.py:


Esto es lo que ocurre cuando lo ejecutamos desde la línea de comandos:


La etiqueta global _ _file_ _, utilizada dentro de un módulo, se refiere al nombre del archivo:


Aquí acaba nuestra introducción a los módulos; si se desea profundizar más en este tema, es posible consultar la sección Módulos del Capítulo 4.

La Python Virtual Machine

En realidad, la instalación de Python no contiene solo un intérprete, sino también un compilador. Cuando un programa es ejecutado, Python compila todos los módulos importados que no han sido modificados desde la última vez en que han sido compilados. Este proceso genera una nueva representación (de nivel bajo) del código, denominada bytecode, la cual es leída y ejecutada por la Python Virtual Machine (PVM). Por tanto no es el código Python lo que se ejecuta, sino el código en bytecode, por lo que el verdadero intérprete, en realidad, es la PVM, la cual ejecuta las instrucciones en bytecode una a una.

A continuación, un ejemplo de instrucciones en bytecode relacionadas con una función que devuelve el cuadrado de un número:



NOTA

Para más información acerca del significado de las instrucciones en byte- code, podemos consultar la documentación en línea del módulo dis: http://docs.python.org/py3k/library/dis.html. Recordad que todos los detalles de implementación tratados en este libro se refieren a CPython.

Cuando se importa un módulo, su versión compilada, si no se expresa de otro modo, se guarda en el sistema de archivos para que pueda ser reutilizada durante las sucesivas ejecuciones del programa, sin que sean necesarias compilaciones posteriores (ver PEP-3147):


Los archivos compilados en bytecode pueden ser ejecutados directamente:


NOTA

En el ejemplo anterior hemos usado diferentes comandos típicos de Unix. Veamos el significado de algunos de ellos. El carácter #, como podemos imaginar, se usa para iniciar un comentario. La instrucción echo "print(_ _name_ _)" > m.py escribe la cadena de texto print(_ _name_ _) en el archivo m.py (si el archivo no existe, lo crea y si existe, lo sobrescribe). El comando ls lista informaciones acerca del archivo y muestra el contenido de los directorios. Las explicaciones del resto de los comandos y de sus opciones forman parte del Apéndice A.

Los módulos Python importados tienen los atributos _ _file_ _ y _ _cached_ _, que son cadenas que representan, respectivamente, el nombre del archivo fuente y el del importado:


NOTA

En la sección Los módulos del Capítulo 3 veremos que algunos módulos (inte- grados y paquetes de espacios de nombres) no se pueden reconducir a un archivo y, por tanto, no tienen los atributos _ _file_ _ y _ _cached_ _.

La etiqueta (tag) que identifica la implementación del intérprete y la versión de Python la da imp.get_tag():


El módulo imp también nos permite obtener el nombre del archivo fuente a partir del nombre del archivo importado y viceversa:


Cuando un módulo Python se ejecuta como script, su bytecode no se guarda en el disco:


NOTA

El comando rm elimina un archivo o un directorio del sistema de archivos. En el caso de un directorio, es preciso utilizar la opción -r.

Sin embargo, podemos solicitar explícitamente su almacenamiento. Para ello, se utiliza la opción -m y se pasa al intérprete el nombre del módulo y no el del archivo:


Si en combinación con la opción -m se utiliza la opción -O, entonces se genera un byte-code optimizado (se eliminan las instrucciones assert), el cual se guarda en un archivo con sufijo .pyo:


NOTA

Ante dos archivos binarios file_A y file_B, el comando diff file_A file_B no muestra ninguna salida si ambos archivos son idénticos; si no, indica que son distintos.

También podemos elegir no guardar en el sistema de archivos las versiones compiladas de los módulos importados. Para ello, podemos utilizar la opción -B:


o bien podemos asignar a la variable de entorno PYTHONDONTWRITEBYTECODE el valor true:


o bien podemos hacerlo cuando el programa se está ejecutando, escribiendo sys.dont_write_bytecode = True:


Etiquetas y objetos

A menudo se dice que todo en Python son objetos. En realidad, como ya hemos dicho en más de una ocasión, los objetos no forman parte del código, sino que este los genera cuando el programa se está ejecutando. En esta sección daremos una definición formal de objeto, recogiendo cuanto hemos sembrado en la primera parte del libro. Además veremos con mayor profundidad cuál es el vínculo entre objetos y etiquetas, puesto que podría no ser evidente de inmediato para aquellos que solo tienen experiencia en programación con lenguajes de tipificación estática.

Definición de objeto

Los objetos en Python son estructuras de datos generadas por el código en ejecución, a las cuales este se refiere. Precisamente, son las expresiones que generan o hacen referencia a los objetos.

Hasta que no se utilizan, los objetos se mantienen en la memoria del ordenador para que puedan ser llamados cuando sean necesarios; sin embargo, en el momento en que no hay ninguna etiqueta que hace referencia a ellos, un mecanismo singular, denominado recolector de basura (garbage collection), procede a liberar la memoria que ocupaban.

NOTA

Podemos gestionar el mecanismo del recolector de basura utilizando el módulo gc, que proporciona una interfaz para el mismo: http://docs.python.org/3/library/gc.html.

Los objetos tienen un tipo y una identidad. Podemos obtener el tipo de un objeto tanto mediante la clase integrada type como mediante el atributo _ _class_ _ del objeto:


La identidad del objeto, que en Python corresponde a su dirección en la memoria, es devuelta por la función integrada id():


Además, observamos que dos objetos diferentes tienen identidades distintas incluso teniendo el mismo valor:


NOTA

Cuando el intérprete encuentra los literales de los tipos mutables, por cuestiones de optimización (independientemente de la implementación), prefiere la reutilización de objetos ya existentes a la creación de otros nuevos, especialmente si se trata de objetos que ocupan poco espacio en memoria:


Cabe señalar que, el hecho de que cada estructura de datos generada por el código Python en ejecución sea un objeto, no significa que el único paradigma de programación soportado sea el de objetos. Como hemos dicho en la sección El estado del arte, Python es un lenguaje multiparadigma.

El vínculo entre las etiquetas y los objetos

Como ya sabemos, en Python no existen las declaraciones, y el tipo de los objetos es establecido cuando el programa se ejecuta. Quizás ahora nos preguntemos cuál es el papel de las etiquetas, puesto que podemos asignar objetos de distintos tipos a la misma etiqueta:


La idea es que una etiqueta es simplemente un identificador mediante el cual se hace referencia al objeto. Esto significa que la primera asignación vincula la etiqueta var al objeto que representa el número 44, de tipo int, como se muestra en la Figura 1.1.


Figura 1.1 - Asignación de la etiqueta var a un número entero de valor 44.

La segunda asignación vincula var a un nuevo objeto, que representa el número 99 y también de tipo int, y ya no existe ninguna vinculación entre var y el objeto que representa el número 44. Además, este último no tiene ninguna etiqueta que haga referencia a aquel, por lo que no puede ser utilizado de ningún modo; Python, por tanto, libera la memoria que ocupaba, como se muestra en la Figura 1.2.


Figura 1.2 - Asignación de la etiqueta var a un nuevo número entero, de valor 99. El 44 deja la memoria libre.

Por último, la tercera asignación vincula var al objeto que representa la cadena 'python', como se muestra en la Figura 1.3.


Figura 1.3 - Asignación de un nuevo objeto de tipo str a la etiqueta var.

Para agilizar la exposición, de ahora en adelante en este libro no volveremos a hablar de objeto que representa a un número o una cadena, sino que diremos simplemente objeto de tipo int, objeto de tipo str, etc. Además, utilizaremos el término referencia para indicar el vínculo entre la etiqueta y el objeto:


Una etiqueta puede ser utilizada solo tras haber sido asignada a un objeto:


NOTA

Como podemos observar en este ejemplo, el término utilizado por el intérprete para indicar lo que nosotros hemos denominado "etiqueta" es name. Gran parte de los libros y de la documentación en inglés también utiliza este término.

Una operación de asignación a una etiqueta ya existente no modifica nunca el objeto que le ha sido asignado:


Esto no siempre es cierto, incluso si el objeto es mutable. Consideremos, por ejemplo, la siguiente lista:


que representamos en la Figura 1.4.


Figura 1.4 - Representación de la referencia entre la etiqueta var y la lista [1, 2, 3].

Si realizamos la asignación var = [1, 2, 3] + [4], aunque la lista sea mutable, el objeto con el identificador 3073876076 no se modifica. Esta instrucción solo tiene como efecto crear un nuevo objeto de tipo lista y asignarlo a la etiqueta `var`:


La lista anterior ya no sirve porque ya no existen más etiquetas que hagan referencia a ella, por lo que Python libera la memoria ocupada, como mostramos de forma esquemática en la Figura 1.5.


Figura 1.5 - La etiqueta var se refiere a la lista [1, 2, 3, 4]. La lista [1, 2, 3] libera la memoria.

El efecto explícito de la asignación es, por tanto, siempre y solo crear un vínculo entre la etiqueta y el objeto a la derecha del signo igual.

Si nos conviene tener una representación visual de lo que sucede cuando en el interior de una expresión hay una etiqueta, podemos pensar (sin cometer ningún error lógico) en que Python sustituye la etiqueta por el objeto al que se refiere.

La creación de las referencias entre etiquetas y objetos se lleva a cabo de la misma forma en todos los modos de asignación, incluso también para el implícito, como, por ejemplo, en el caso de las etiquetas asignadas implícitamente en las instrucciones for:


donde la etiqueta item para cada iteración se refiere al correspondiente objeto incluido en la lista.

Otro caso de asignación implícita es el paso de los argumentos a una función, en el cual las etiquetas utilizadas como parámetros hacen referencia a los respectivos objetos pasados como argumentos, y no a su copia:


En realidad, cuando se realiza la llamada foo(a, b), se llevan a cabo las asignaciones implícitas par1=a y par2=b, y podemos pensar que a será sustituida por el objeto al cual hace referencia, igual que b.

También la definición de una función da lugar a una asignación implícita. La instrucción def crea un objeto función y lo asigna a la etiqueta situada entre la def y los paréntesis:



Con la indexación se obtiene el mismo comportamiento. Por ejemplo, en el código siguiente podemos pensar que mylist[0], mylist[1] y mylist[2] serán sustituidos por los objetos a los cuales hacen referencia:


₺548,57

Türler ve etiketler

Yaş sınırı:
0+
Hacim:
1892 s. 2471 illüstrasyon
ISBN:
9788426729057
Yayıncı:
Telif hakkı:
Bookwire
İndirme biçimi:
Metin
Ortalama puan 0, 0 oylamaya göre
Ses
Ortalama puan 0, 0 oylamaya göre
Metin
Ortalama puan 0, 0 oylamaya göre
Metin
Ortalama puan 4,8, 5 oylamaya göre
Metin
Ortalama puan 0, 0 oylamaya göre
Metin
Ortalama puan 0, 0 oylamaya göre
Metin
Ortalama puan 0, 0 oylamaya göre