Cómo encontrar dónde vive una función
Una base de código es todo el código de un programa. En tu primer día de trabajo te dan una que escribieron otros, con miles de líneas y sin mapa.
Nadie la lee entera. Aprendes a hacer una pregunta, buscar la respuesta y seguir las llamadas desde allí.
Al terminar esta lección
Nota
Puedo encontrar dónde vive una función en código ajeno y seguir una llamada de un archivo al siguiente.
Palabras clave
| Palabra | Qué significa |
|---|---|
| Base de código | todos los archivos de código de un programa |
| Punto de entrada | el archivo o la función donde empieza a correr un programa |
| Búsqueda | mirar en todos los archivos una palabra, con una herramienta como grep |
| Llamador | una línea de código que usa una función |
| Cadena de llamadas | las funciones a las que lleva una llamada, una tras otra |
| Prueba como documentación | una prueba que muestra, en código, lo que promete una función |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Empieza con una pregunta, no con un archivo
No abras el primer archivo para leer hacia abajo. Haz una pregunta pequeña: ¿dónde se calcula el descuento del cupón?
Mira primero la forma de las carpetas. Ejecuta el programa para ver qué hace. Después busca una palabra que veas en pantalla.
Crea primero el proyecto. Una carpeta de caché oculta metería ruido en las búsquedas, así que el primer Run la desactiva.
Evita que Python cree carpetas de caché
export PYTHONDONTWRITEBYTECODE=1Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Crea las dos carpetas
mkdir -p ~/readcode/shop ~/readcode/testsSe muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Entra en el proyecto
cd ~/readcodeSe muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Escribe la lista de precios
printf 'PRICES = {"te": 250, "taza": 899, "libro": 1200}\n\n\ndef unit_price(code):\n return PRICES[code]\n' > shop/prices.pySe muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Escribe los cupones
printf 'COUPONS = {"AHORRA10": 10, "MITAD": 50}\n\n\ndef discount_percent(code):\n return COUPONS.get(code, 0)\n' > shop/discounts.pySe muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Escribe el total del pedido
printf 'from shop.prices import unit_price\nfrom shop.discounts import discount_percent\n\n\ndef order_total(items, coupon=None):\n total = 0\n for code, count in items:\n total = total + unit_price(code) * count\n percent = discount_percent(coupon)\n return total - total * percent // 100\n' > shop/orders.pySe muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Escribe la orden
printf 'import sys\nfrom shop.orders import order_total\n\n\ndef main(args):\n items = [("te", 2), ("taza", 1)]\n coupon = args[0] if args else None\n print(order_total(items, coupon))\n\n\nmain(sys.argv[1:])\n' > shop/cli.pySe muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Escribe las pruebas
printf 'import unittest\nfrom shop.orders import order_total\n\n\nclass OrderTest(unittest.TestCase):\n def test_no_coupon(self):\n self.assertEqual(order_total([("te", 2)]), 500)\n\n def test_ahorra10(self):\n self.assertEqual(order_total([("te", 2)], "AHORRA10"), 450)\n' > tests/test_orders.pySe muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Mira la forma del proyecto
ls -RSe muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Ejecútalo con un cupón
python3 -m shop.cli AHORRA10Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Busca una palabra que ves
El programa imprimió 1260. El cupón se llamaba AHORRA10, y esa palabra tiene que estar escrita en algún sitio. grep -rn busca en todos los archivos bajo las carpetas que nombres, e imprime el archivo, el número de línea y la línea.
Un nombre que ves en pantalla es la mejor entrada a un código que no conoces.
Busca el nombre del cupón
grep -rn "AHORRA10" shop testsSe muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Sigue la llamada al siguiente sitio
La búsqueda halló una tabla de cupones en discounts.py. Una tabla no hace nada sola, así que haz la siguiente pregunta: ¿quién la usa?
Busca la función que lee la tabla. Una línea la define, otra la importa y otra la llama. La llamada es donde el descuento llega al pedido.
Encuentra cada uso de la función
grep -rn "discount_percent" shopSe muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Ejemplo resuelto: la cadena de una orden
| Paso | Archivo y línea | Qué ocurre |
|---|---|---|
| 1 | shop/cli.py, main | El punto de entrada lee el cupón de la línea de órdenes |
| 2 | shop/orders.py, order_total | Suma los precios y pide el descuento |
| 3 | shop/prices.py, unit_price | Da el precio de un artículo |
| 4 | shop/discounts.py, discount_percent | Busca el cupón, o da 0 |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Lee las pruebas: dicen lo que promete
Una buena prueba dice lo que debe hacer una función, con entradas reales y sus respuestas. Es la única documentación que no se queda anticuada, porque falla cuando lo hace.
Lista los nombres de las pruebas y ejecútalas. Si pasan, lo que leíste es cierto hoy.
Lista las pruebas
grep -n "def test" tests/test_orders.pySe muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Ejecuta las pruebas
python3 -m unittest discover -s tests 2>&1 | grep -E "^(OK|FAILED)"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Un error frecuente
Advertencia
Mucha gente lee todos los archivos desde arriba, esperando entenderlo todo antes. Lleva días y casi nada trata de tu pregunta. Haz una pregunta, busca, sigue la llamada y para cuando puedas responderla.
Más lejos: un proyecto mayor
Elige un proyecto que uses, con su código fuente en tu máquina. Escoge algo que haga, como leer un archivo de ajustes.
Anota la pregunta, la palabra que buscaste y la cadena de archivos que seguiste. ¿Cuántos pasos fueron?