Saltar al contenido principal
LibreTexts Español

2.12: Interfaces de Programación de Aplicaciones, Módulos, Paquetes, Azúcar Sintáctico

  • Page ID
    55099
  • \( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \) \( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)\(\newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\) \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\) \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\) \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\) \( \newcommand{\Span}{\mathrm{span}}\) \(\newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\) \( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\) \( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\) \( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\) \( \newcommand{\Span}{\mathrm{span}}\)\(\newcommand{\AA}{\unicode[.8,0]{x212B}}\)

    Sabemos que los objetos como listas tienen métodos como .sort () y .append (). ¿Tienen otros? Lo hacen, y una forma de encontrarlos es ejecutar Python en el modo interactivo en la línea de comandos. [1]

    Para ello, ejecutamos el intérprete python sin especificar un archivo a interpretar. El resultado es un prompt de Python, >>>, donde podemos escribir líneas individuales de código Python y ver los resultados.

    II.12_1_py_115_interactive_ex

    El modo interactivo, además de proporcionar una interfaz para ejecutar pruebas rápidas de la funcionalidad de Python, ¡incluye un sistema de ayuda! Simplemente ejecute la función help () en un nombre de clase (como help (list)) o en una instancia de la clase.

    II.12_2_py_116_interactive_help_list1

    Este comando abre un visor interactivo en el que podemos desplazarnos para ver todos los métodos que proporciona un objeto de ese tipo. Aquí hay una muestra de la página de ayuda:

    II.12_3_py_117_interactive_help_list2

    Navegar por esta documentación revela que las listas de Python tienen muchos métodos, incluyendo .append (), .count () y otros. A veces la documentación no es tan clara como cabría esperar. En estos casos, puede requerirse alguna experimentación. Entre la descripción anterior y algunas pruebas de código, por ejemplo, ¿puedes determinar qué hace el método .count () de una lista y cómo usarlo de manera efectiva?

    El conjunto de métodos y variables de instancia que pertenecen a un objeto o clase se conoce como su API, o Interfaz de Programación de Aplicaciones. La API es el conjunto de funciones, métodos o variables proporcionadas por una colección encapsulada de código. Las APIs son una parte importante de la programación porque representan la “interfaz de usuario” para los constructos de programación que otros han escrito.

    En ocasiones puede ser útil determinar qué clase o “tipo” a la que se refiere una variable, especialmente para buscar en la API objetos de ese tipo. La función type () es útil cuando se combina con una llamada print (): imprime el tipo (la clase) de datos referenciados por una variable. El resultado puede entonces ser investigado con help ().

    II.12_4_py_117_2_type_api

    Módulos

    Considere este trozo de código del ejemplo del capítulo 23, “Objetos y clases”, que hace uso de las definiciones de las clases Cromosoma y SNP:

    imagen

    Este segmento de código toma un nombre de archivo y produce un diccionario con contenidos bien organizados del archivo. Debido a que esta funcionalidad está definida de manera sucinta, tiene sentido convertirla en una función que tome el nombre del archivo como parámetro y devuelva el diccionario. El código es casi exactamente el mismo, excepto por estar envuelto en una definición de función.

    imagen

    Posteriormente, podemos llamar a esta función para hacer todo el trabajo de analizar un nombre de archivo dado:

    imagen

    Ahora bien, ¿y si esta función y las dos definiciones de clase fueran cosas que queríamos usar en otros proyectos? Es posible que deseemos hacer un módulo con ellos, un archivo que contenga código Python (generalmente relacionado con un solo tema, como un conjunto de funciones o definiciones de clase relacionadas con un tipo particular de datos o procesamiento).

    Ya hemos visto varios módulos, incluyendo io, re y sys. Para usar un módulo, solo necesitamos ejecutar import modulename. Resulta que los módulos son simplemente archivos de código Python que terminan en ¡.py! Así, cuando usamos import modulename, el intérprete busca un modulename.py que contenga las distintas definiciones de función y clase. Los archivos de módulo pueden existir en una ubicación de todo el sistema, o estar presentes en el directorio de trabajo del programa importándolos. [2]

    Importar el módulo de esta manera crea un espacio de nombres para el módulo. Este espacio de nombres categoriza todas las funciones y clases contenidas dentro de ese módulo para que diferentes módulos puedan tener funciones, clases y variables con el mismo nombre sin conflicto.

    II.12_8_Two_Módulos

    Si tenemos los dos archivos anteriores en el mismo directorio que nuestro programa, el código fuente como el siguiente imprimiría 4, 64, “TAC” y 2.71828.

    imagen

    Desafortunadamente, Python usa el. operador de múltiples maneras similares, como indicar un método que pertenece a un objeto (como en a_list.append (“ID3")) y para indicar una función, variable o definición de clase perteneciente a un espacio de nombres (como arriba).

    Así, como un “contenedor” para los nombres, el espacio de nombres permite a diferentes módulos nombrar funciones, clases y variables de la misma manera sin entrar en conflicto. Así como una clase puede ser documentada por su API, también lo pueden hacer los módulos: la API de un módulo describe las funciones, clases y variables que define. También se puede acceder a ellos a través del menú de ayuda interactiva (y en línea). Intente ejecutar import re seguido de help (re) para ver todas las funciones proporcionadas por el módulo re.

    imagen

    Hay una gran cantidad de módulos (y paquetes) disponibles para descargar en línea, y Python también viene con una amplia variedad de módulos útiles por defecto. Aparte de re, sys e io, discutidos anteriormente, algunos de los módulos potencialmente más interesantes incluyen:

    • string: operaciones de cadena comunes (cambio de mayúsculas y minúsculas, formateo, etc.)
    • hora, fechahora y calendario: operaciones en fechas y horas
    • random: generar y trabajar con números aleatorios
    • argparse: análisis fácil de usar de argumentos complejos en la línea de comandos
    • Tkinter: creación de interfaces gráficas de usuario (con botones, barras de desplazamiento, etc.)
    • unittest: automatizar la creación y ejecución de pruebas unitarias
    • turtle: una interfaz simple para mostrar gráficos basados en líneas [3]

    Los tutoriales para estos módulos específicos se pueden encontrar en línea, así como listas de muchos otros paquetes y módulos que vienen instalados con Python o que están disponibles para su descarga.

    Creación de un módulo

    Vamos a crear un módulo llamado MyVCFModule.py para contener las dos definiciones de clase y la función de análisis del último ejemplo. Mientras lo hacemos, también convertiremos los comentarios que habíamos creado para nuestras clases, métodos y funciones en “docstrings”. Las cadenas de documentos son cadenas de comillas triples que proporcionan una funcionalidad similar a los comentarios, pero se pueden analizar posteriormente para producir la API del módulo. Pueden abarcar varias líneas, pero deben ocurrir inmediatamente dentro de la definición de módulo, clase o función correspondiente. Aquí dejamos fuera el contenido de los métodos y funciones (que son los mismos que en el capítulo anterior) para ahorrar espacio:

    alt

    El programa que hace uso de este módulo, que existe en un archivo separado en el mismo directorio (quizás llamado snps_ex2.py), es corto y dulce. [4]

    imagen

    Si otros proyectos necesitan analizar archivos VCF, este módulo puede ser de nuevo de utilidad. Por cierto, debido a que documentamos nuestro módulo con docstrings, su API es fácilmente accesible a través de la interfaz de ayuda interactiva.

    imagen

    Parte de la página de ayuda de la API:

    imagen

    Paquetes

    Como si Python no tuviera ya suficientes “cajas” para la encapsulación —funciones, objetos, módulos, etc.— también hay paquetes. En Python, un “paquete” es un directorio que contiene algunos archivos de módulo. [5]

    Un directorio de paquetes también debe contener un archivo especial llamado __init__.py, que le permite a Python saber que el directorio debe tratarse como un paquete desde el que se pueden importar módulos. (Se podría poner código en este archivo que se ejecutaría cuando se ejecute la sentencia import, pero no exploraremos esta característica aquí).

    alt

    Como ejemplo, supongamos que junto con nuestro MyVCFModule.py, también habíamos creado un módulo para analizar archivos de ontología génica llamado GOParseModule.py. Podríamos juntarlos en un paquete (directorio) llamado MyBioParsers.

    Para usar un módulo contenido en un paquete, la sintaxis es de packagename import modulename. [6] Nuestro programa Python podría vivir en el mismo directorio en el que se encontró el directorio MyBioParsers, y podría comenzar así:

    imagen

    Posteriormente, el propio módulo se puede utilizar igual que antes.

    imagen

    Analizar un archivo FASTA

    Hasta este punto, nos hemos saltado algo que es ampliamente considerado un “básico” en biología computacional: leer un archivo FASTA. En su mayor parte, los ejemplos anteriores que necesitan datos de secuencia leen esos datos de archivos simples con formato de fila/columna.

    imagen

    La mayoría de los datos de secuencia, sin embargo, aparecen en el llamado formato FASTA, donde cada secuencia tiene una línea de cabecera que comienza con > y un ID, y la secuencia se divide en cualquier número de líneas siguientes antes de que aparezca la siguiente línea de cabecera.

    imagen

    Analizar datos en formato FASTA no es demasiado difícil, pero requiere un paso de preprocesamiento adicional (generalmente implica un bucle y una variable que realiza un seguimiento del ID “actual”; siempre que las líneas posteriores no coincidan con el carácter >, deben ser líneas de secuencia y pueden agregarse a una lista de cadenas para luego unirse para esa identificación). Si bien reinventar la rueda de análisis FASTA es una buena práctica para los codificadores novatos, el paquete BioPython proporciona funciones para analizar estos y muchos otros formatos. [7]

    BioPython es un paquete grande con muchos módulos y APIs, sobre los que puedes leer más en http://biopython.org. Para la aplicación específica de análisis de un archivo FASTA, un buen lugar para comenzar es una simple búsqueda web de “biopython fasta”, que nos lleva a una página wiki que describe el módulo SeqIO, completa con un ejemplo.

    II.12_20_Biopython_wiki_shot

    Esta captura de pantalla muestra algunas diferencias con la forma en que hemos estado escribiendo código, por ejemplo, el uso de open () en contraposición a io.open (), y la llamada a print record.id en lugar de nuestra habitual print (record.id) (la primera de las cuales funcionará solo en versiones anteriores de Python, mientras que esta última funcionará en todas las versiones razonablemente recientes de Python). Sin embargo, dado nuestro conocimiento de paquetes, módulos y objetos, podemos deducir lo siguiente de este sencillo ejemplo de código:

    1. El módulo SeqIO se puede importar desde el paquete Bio.
    2. Se abre un manejador de archivo.
    3. Se llama a la función seqio.parse (), y toma dos parámetros: el identificador del archivo desde el que leer los datos, y una cadena de especificación que describe el formato del archivo.
    4. Esta función devuelve algo iterable (similar a una lista, o un identificador de archivo normal), por lo que se puede enrollar con un bucle for.
    5. El bucle accede a una serie de objetos de algún tipo, y cada uno se asocia con el registro de nombre de variable.
    6. Se imprime el registro.id, que es (aparentemente) una variable de instancia que pertenece al objeto record.
    7. El mango del archivo está cerrado (¡siempre buena práctica!).

    Si hacemos un poco más de lectura en la página wiki de SeqIO, encontraríamos que los objetos de registro realmente tienen la clase SeqRecord, y también tienen una variable de instancia seq que proporciona acceso a la secuencia completa.

    Al juntar todo esto, aquí hay un programa corto que convierte un archivo FASTA al formato de fila/columna con el que hemos estado tratando.

    imagen

    Azúcar Sintáctico

    En Python, casi todo es un objeto, ¡incluso enteros simples! Al mirar la API de un entero, por ejemplo, descubrimos que proporcionan un método llamado .bit_length ().

    imagen

    Aquí hay una parte de la vista de API:

    imagen

    Podemos probarlo así, para descubrir que el entero 7 se puede representar con tres bits binarios (como 111):

    imagen

    Si intentaras ver la API para un entero como lo hemos hecho, verías una serie de métodos de aspecto impar, como. __add__ () y. __abs__ ():

    imagen

    Esto parece indicar que podemos obtener el valor absoluto de un entero mediante el uso de una llamada a un método o mediante el uso de la sintaxis de llamada a la función estándar. Del mismo modo, aparentemente podemos agregar un entero a otro mediante el uso de la llamada al método o el operador estándar +. Estos son realmente ciertos, y podemos usar las funciones y operadores estándar o sus versiones de método:

    imagen

    Las operaciones como la adición parecen operaciones básicas y fundamentales, y Python realiza tales operaciones a través de llamadas a métodos en objetos. [8] Una declaración como a = b + c se convierte en a = b.__add__ (c) detrás de escena. Aunque podemos ejecutar tales operaciones orientadas a métodos nosotros mismos, la incómoda sintaxis de doble subrayado es cómo los diseñadores nos hacen saber que esos métodos son para uso interno, y debemos seguir con la sintaxis estándar. Esta conversión automática de sintaxis se conoce como azúcar sintáctica, y está presente en muchos lenguajes de programación para que puedan ser internamente consistentes pero más agradables (“más dulces”) para que los humanos trabajen con ellos.

    Ejercicios

    1. Cree un módulo llamado mymodule.py que incluya al menos una definición de clase y definición de función, así como documente el módulo, clase, métodos y funciones con docstrings. Crear un myprogram.py que importe este módulo y haga uso de la funcionalidad en él. También intente ver la API para su módulo en el intérprete interactivo de Python con import mymodule y help (mymodule).
    2. Navegue a través de la API en línea en http://docs.python.org/2/library para obtener la “Biblioteca estándar de Python” y especialmente cualquier cosa relacionada con cadenas. Además, revise la documentación de la API para los módulos io, sys, re, math y random.
    3. Para este ejercicio, vamos a instalar un módulo desde la web y hacer uso de él para analizar un archivo VCF trio.sample.vcf. El módulo de lectura VCF que vamos a instalar se encuentra en GitHub (un lugar cada vez más popular para alojar software): https://github.com/jamescasbon/PyVCF.

      Lo primero que hay que hacer es clonar este repositorio desde el enlace .git (que requiere que tengamos instalada la herramienta git). Esta clonación debería descargar una carpeta PyVCF; cd hasta allí y usar ls para ver el contenido:imagen A continuación, necesitamos instalarlo, esto configurará el módulo y sus archivos necesarios, y los colocará en una carpeta oculta llamada .local dentro de su directorio principal ( Python también busca allí módulos y paquetes por defecto). Para introducirlo en .local en tu propio directorio home en lugar de usar una instalación en todo el sistema (que quizás no tengas permiso para hacer), tenemos que agregar —user al comando que ejecuta el script setup.py:imagen Una vez hecho esto, vuelve a tu directorio original, y entonces puedes activar el intérprete interactivo de Python, cargar el módulo y ver su API:imagen (Lamentablemente, la documentación de la API en el paquete en sí no es tan buena, la versión en línea en http://pyvcf.rtfd.org es mejor, específicamente en la introducción).

    4. Escribe un programa llamado vcf_module_use.py que importe este módulo vcf y lo utilice para contar e imprimir cuántas líneas en trio.sample.vcf tienen un alelo de referencia de “A. (Tenga en cuenta que debe importar y usar el módulo, en lugar de analizar cada línea usted mismo).

    1. Gran parte de esta información también está disponible en línea en http://docs.python.org.
    2. Los módulos y paquetes de Python no necesitan estar instalados en todo el sistema o estar presentes en el mismo directorio que el programa que los usa. La variable de entorno $PYTHONPATH enumera los directorios que se buscan por módulos y paquetes, a los que cada usuario es libre de agregar sus propias rutas de búsqueda.
    3. El módulo de gráficos tortuga es una forma divertida de entender y visualizar procesos computacionales (y paquetes similares están disponibles para muchos lenguajes de programación). Si bien este libro no es el lugar para tales exploraciones, el lector puede aprender más sobre ellas en el excelente libro de Jeffrey Elkner, Allen Downey y Chris Meyers, How to Think Like a Computer Scientist (Green Tea Press, 2002). Al momento de escribir este artículo, una versión del libro está disponible en línea en http://interactivepython.org/runestone/static/thinkcspy/index.html.
    4. En algunos scripts de Python, puede encontrar una línea si __name__ == '__main__':. El código dentro de esta sentencia if se ejecutará, pero solo si el archivo se ejecuta como un script. Si se importa como módulo, el bloque no se ejecutará. Esto permite a los desarrolladores escribir archivos que pueden servir para ambos propósitos, y muchos desarrolladores lo incluyen por defecto para que las funciones de su script y las definiciones de clase puedan ser utilizadas en el futuro importando el archivo como un módulo.
    5. Los paquetes también pueden contener otros archivos, como archivos que contienen conjuntos de datos específicos o incluso código escrito en otros idiomas como C. Por lo tanto, algunos módulos pueden necesitar ser instalados por procesos más complicados que simplemente descomprimirlos en la ubicación correcta.
    6. Es posible que ocasionalmente vea una línea como de modulename import *. Esto permite usar las funciones y otras definiciones dentro de modulename sin prefijarlas con modulename. . Por ejemplo, podemos importar matemáticas y luego usar print (math.sqrt (3.0)), o podemos desde math import * y luego print (sqrt (3.0)). Esto último generalmente se evita, porque si múltiples módulos contienen la misma función u otros nombres, entonces no es posible desambiguarlos.
    7. Dependiendo del sistema en el que estés trabajando, es posible que ya tengas el paquete BioPython. Si no, puedes usar la utilidad pip install para instalarlo: pip install BioPython, o si no tienes privilegios de administrador, pip install —user BioPython. Algunas versiones anteriores de Python no vienen con la utilidad pip, pero esta se puede instalar con una herramienta más antigua: easy_install pip o easy_install —user pip.
    8. Es seguro decir que Python no está “meramente” orientado a objetos, está muy orientado a objetos.

    This page titled 2.12: Interfaces de Programación de Aplicaciones, Módulos, Paquetes, Azúcar Sintáctico is shared under a CC BY-NC-SA license and was authored, remixed, and/or curated by Shawn T. O’Neil (OSU Press) .