Saltar al contenido principal
LibreTexts Español

2.6: Funciones de Python

  • Page ID
    55081
  • \( \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}}\)

    El perfil psicológico [de un programador] es principalmente la capacidad de cambiar los niveles de abstracción, de nivel bajo a nivel alto. Para ver algo en lo pequeño y ver algo en lo grande.

    ~ Donald Knuth

    Las funciones (a veces llamadas “subrutinas”) son posiblemente el concepto más importante en la programación. Ya hemos visto su uso en muchos contextos, por ejemplo, al usar funciones como len () y float (). Aquí hay un poco de código que calcula el contenido de GC de una secuencia de ADN en una variable llamada seq:

    II.6_1_PY_50_2_GC_Loop

    ¿Y si quisiéramos calcular el contenido de GC para múltiples variables diferentes en nuestro código? ¿Deberíamos reescribir nuestro for-loop de GC-Computing para cada variable diferente? ¡De ninguna manera! Primero, estaríamos en un riesgo mucho mayor de errores (es un hecho probabilístico que más mecanografía lleva a más errores tipográficos). Segundo, el objetivo de la programación es que la computadora haga todo el trabajo, no nosotros.

    Idealmente, nos gustaría encapsular la funcionalidad de calcular el contenido de GC, así como la funcionalidad de obtener la longitud de una secuencia está encapsulada por la función len (). Sólo queremos poder decir gc = gc_content (seq). Las funciones nos permiten hacer exactamente esto: encapsular un bloque de código para reutilizarlo siempre que lo necesitemos. Hay tres partes importantes de una función:

    1. La entrada (parámetros dados a la función).
    2. El bloque de código que se va a ejecutar usando esos parámetros. Como es habitual, un nivel adicional de sangría definirá el bloque.
    3. La salida de la función, llamada el valor de retorno. Esto puede ser opcional, si la función “hace algo” (como print ()) en lugar de “devuelve algo” (como len ()).

    Ignorando el punto 2, las funciones pueden representar realmente un ideal matemático: relacionan entradas con salidas. Incluso tienen dominios (el conjunto de todas las entradas válidas) y rangos (el conjunto de todas las salidas potenciales).

    Definimos funciones en Python usando la palabra clave def, y en Python las funciones deben definirse antes de que puedan ser ejecutadas. Aquí hay una función de ejemplo que calcula una “composición base” (recuento de un carácter en una cadena dada) dado dos parámetros: (1) la secuencia (una cadena) y (2) la base/carácter a buscar (también una cadena).

    alt

    Las dos últimas líneas anteriores llaman a la función con diferentes parámetros; tenga en cuenta que los nombres de las variables de parámetros (en este caso seq y query_base) no necesitan relacionarse con los nombres de las variables de los datos fuera de la función. Este es un punto importante al que volveremos. Cuando el intérprete lee la línea def y el bloque correspondiente, se define la función (disponible para su uso), pero las líneas no se ejecutan, ni se llaman, hasta que la función se usa en las dos últimas líneas.

    Una de las mejores cosas de las funciones es que pueden llamar a otras funciones, siempre que ya se hayan definido en el momento en que se llaman.

    II.6_3_PY_52_base_composición_función_2

    Debido a que las funciones solo necesitan ser definidas antes de ser llamadas, es común ver colecciones de funciones primero en un programa. Además, el orden de definición no necesita corresponder a su orden de ejecución: ya sea la definición de función gc_content () o base_composition () podrían ocurrir primero en este archivo y el cálculo seguiría funcionando.

    La idea de encapsular ideas pequeñas en funciones de esta manera es poderosa, y desde este punto en adelante se debe intentar pensar principalmente en términos de “qué función estoy escribiendo/necesito”, en lugar de “¿qué programa estoy escribiendo?”

    Notas importantes sobre las funciones

    En un esfuerzo por producir código limpio, legible y reutilizable, debe esforzarse por seguir estas reglas al escribir funciones.

    1. Los bloques de función solo deben utilizar variables que se crean dentro del bloque de función (por ejemplo, g_cont y c_cont dentro de la función gc_content () anterior), o se pasan como parámetros (por ejemplo, seq). Las funciones deben ser “mundos en sí mismos” que sólo interactúan con el mundo exterior a través de sus parámetros y declaración de retorno. La siguiente redefinición de la función gc_content () funcionaría, pero se consideraría de mala forma porque se usa seq4 pero no es uno de los dos tipos enumerados. imagenObserve la diferencia: la función no toma parámetros y por lo tanto debe usar los mismos nombres de variables definidos fuera de la función. Esto hace que la función esté fuertemente ligada al contexto en el que se le llama. Debido a que las definiciones de funciones pueden ser cientos o miles de líneas eliminadas de donde se les llama (o incluso están presentes en un archivo diferente), esto hace que la tarea de codificar sea mucho más difícil.
    2. Documentar el uso de cada función con comentarios. ¿Qué parámetros se toman y qué tipos deberían ser? ¿Es necesario que los parámetros se ajusten a alguna especificación? Por ejemplo: “esta función sólo funciona para cadenas de ADN, no cadenas de ARN”. ¿Qué se devuelve? Aunque anteriormente hemos comentado nuestras funciones mediante el uso de líneas de comentarios simples, Python le permite especificar un tipo especial de comentario de función llamado “docstring”. Estas cadenas de comillas triples deben aparecer en la parte superior del bloque de función y pueden abarcar varias líneas. II.6_5_py_54_función_docstringMás tarde, cuando discutamos la documentación para el código Python, aprenderemos cómo el intérprete de Python puede recopilar automáticamente estos comentarios en documentos agradables y legibles por humanos para otros que quieran llamar a sus funciones. De lo contrario, usaremos comentarios regulares para la documentación de funciones.
    3. Las funciones no deberían ser “demasiado largas”. Esto es subjetivo y depende del contexto, pero la mayoría de los programadores se sienten incómodos con funciones que tienen más de una página de largo en su ventana de editor. [1] La idea es que una función encapsula una idea única, pequeña y reutilizable. Si te encuentras escribiendo una función que es difícil de leer o entender, considera dividirla en dos funciones que necesitan ser llamadas en secuencia, o en una función corta que llama a otra función corta.
    4. ¡Escribe muchas funciones! Incluso si una sección de código sólo va a ser llamada una vez, es completamente aceptable hacer una función fuera de ella si encapsula alguna idea o bloque bien separable. Después de todo, nunca se sabe si podría necesitar volver a usarlo, y solo el acto de encapsular el código te ayuda a asegurar su corrección, permitiéndote olvidarte de él cuando trabajas en el resto de tu programa.

    Contenido de GC sobre secuencias en un archivo

    En el capítulo 17, “Flujo de control condicional”, uno de los ejercicios consistió en calcular el peso molecular para cada secuencia en un archivo separado por tabuladores de IDs y secuencias, ids_seqs.txt. Aquí están las líneas de este archivo visto con menos -S:

    II.6_6_py_55_short_seqs_ids_less

    Si completaste el ejercicio de peso molecular en el capítulo 17, es posible que te haya resultado algo desafiante. Sin usar funciones, es probable que necesite usar un bucle for para iterar sobre cada línea del archivo, y dentro de allí otro bucle for para iterar sobre cada base de la secuencia actual, y dentro de eso una sentencia if para determinar el peso molecular de cada base.

    Aquí escribiremos un programa similar, excepto que esta vez haremos uso de una función que devuelve el contenido GC de su parámetro. Toda la solución es en realidad bastante corta y legible.

    II.6_7_PY_56_GC_Lines_EX

    En el código anterior (ids_seqs_gcs.py), hay una clara “separación de preocupaciones” que facilita el diseño de una solución. Una función maneja el conteo de bases en una secuencia de ADN y otra el cálculo del contenido de GC. Con esos fuera del camino, podemos enfocarnos en analizar el archivo de entrada e imprimir la salida.

    Para simplificar la exposición, la mayoría de las pequeñas muestras de código en los próximos capítulos no implican la creación de nuevas funciones. Sin embargo, la mayoría de los ejercicios sugerirán funciones de escritura como un medio para descomponer un problema en sus partes componentes.

    Ejercicios

    1. Ahora hemos cubierto cuatro de las estructuras básicas de flujo de control comunes a la mayoría de los lenguajes de programación. ¿Qué son y qué hacen?
    2. A menudo queremos mirar algún tipo de ventanas de una secuencia; tal vez queremos mirar los codones de una secuencia como “ACTTAGAGC” (“ACT”, “TAG” y “AGC”), que podemos pensar como un “tamaño de ventana” de 3 pb y un “tamaño de paso” de 3 pb. O tal vez queremos considerar ventanas superpuestas de 6-mers (como “ACTTAG”, “CTTAGA”, “TTAGAG”, y “TAGAGC”, tamaño de ventana 6, tamaño de paso 1).

      Escribe un programa con una función llamada get_windows () que tome tres parámetros: la secuencia para extraer ventanas de (string), el tamaño de la ventana (int) y el tamaño del paso (int). La función debería devolver una lista de cadenas, una por ventana, sin “ventanas parciales” si la última ventana se corría fuera del final de la secuencia. II.6_8_py_56_2_get_windows_exercise(Puede encontrar un bucle de tiempo para ser más útil que un bucle for para este ejercicio). Usa este código para probar tu función:II.6_9_py_56_3_get_windows_ex_use Este código debería generar lo siguiente:II.6_10_py_56_4_get_windows_ex_use_out

    3. Aunque la función get_windows () está diseñada para ejecutarse en cadenas, la indexación en cadenas y en listas funciona igual en Python. ¿Qué pasa si ejecutas get_windows ([1, 2, 3, 4, 5, 6, 7, 8], 3, 2)?
    4. Rehacer el ejercicio 1 del capítulo 17, pero esta vez escribe y usa una función molecular_weight () que toma una cadena de ADN como parámetro llamado seq.

    1. Con el advenimiento de los monitores grandes, ¡quizás esta ya no sea una buena regla general! Personalmente, encuentro que pocas de mis funciones necesitan superar las 30 líneas de longitud, dependiendo sólo algo del idioma en el que esté escribiendo.

    This page titled 2.6: Funciones de Python is shared under a CC BY-NC-SA license and was authored, remixed, and/or curated by Shawn T. O’Neil (OSU Press) .