""

sábado, 19 de abril de 2025

Thinkcspy. Funciones / 6.11 Un grafico de barras dibujado en turtle

 

6.11. Un gráfico de barra de tortuga

Recuerde de nuestra discusión de los módulos que había varias cosas que las tortugas pueden hacer. Aquí hay un par de trucos más (recuerde que todos se describen en la documentación del módulo).

  • Podemos obtener una tortuga para mostrar texto en el lienzo en la posición actual de la tortuga. Se llama al método write. Por ejemplo, alex.write("Hello") Escribiría la cadena Hello en la posición actual.

  • Uno puede llenar una forma (círculo, semicírculo, triángulo, etc.) con un color de relleno. Es un proceso de dos pasos. Primero llamas al método begin_fill, Por ejemplo alex.begin_fill(). Luego dibujas la forma. Finalmente, llamas end_fill ( alex.end_fill()).

  • Anteriormente hemos establecido el color de nuestra tortuga; ahora también podemos establecer su color de relleno, que no necesita ser lo mismo que la tortuga y el color de la pluma. Para hacer esto, utilizamos un método llamado fillcolor, Por ejemplo, alex.fillcolor("red").

Ok, entonces, ¿podemos hacer que Tess dibuje un gráfico de barras? Comencemos con algunos datos para ser trazados,

xs = [48, 117, 200, 240, 160, 260, 220]

En correspondencia con cada medición de datos, dibujaremos un rectángulo simple de esa altura, con un ancho fijo. Aquí hay una versión simplificada de lo que nos gustaría crear. 

../_images/tess_bar_1.png 

Podemos ver rápidamente que dibujar una barra será similar a dibujar un rectángulo o un cuadrado. Dado que tendremos que hacerlo Varias veces, tiene sentido crear una función, drawBar, que necesitará una tortuga y la altura de la barra. Asumiremos que el ancho de la barra será de 40 unidades. Una vez que tenemos la función, podemos usar un bucle básico para procesar la lista de valores de datos.

>>def drawBar(t, height):
    """ Get turtle t to draw one bar, of height. """
>>    t.left(90)               # Point up
>>    t.forward(height)        # Draw up the left side
>>    t.right(90)
>>    t.forward(40)            # width of bar, along the top
>>    t.right(90)
>>    t.forward(height)        # And down again!
>>    t.left(90)               # put the turtle facing the way we found it.

...
>>for v in xs:                 # assume xs and tess are ready
>>    drawBar(tess, v)


¡Es un buen comienzo! Lo importante aquí fue la fusión mental. Para resolver el problema, primero lo dividimos en piezas más pequeñas. En particular, Nuestro trozo es dibujar una barra. Luego implementamos ese fragmento con una función. Entonces, para el todo Gráfico, repetidamente llamamos nuestra función.

A continuación, en la parte superior de cada barra, imprimiremos el valor de los datos. Haremos esto en el cuerpo de drawBar Al agregar t.write(str(height)) Como la nueva cuarta línea del cuerpo. Tenga en cuenta que tuvimos que girar el número en una cadena. Finalmente, agregaremos los dos métodos necesarios para llenar cada barra.

El único problema restante está relacionado con el hecho de que nuestra tortuga vive en un mundo donde la posición (0,0) está en el centro del lienzo de dibujo. En este problema, ayudaría si (0,0) estuvieran en la esquina inferior izquierda. Para resolver esto podemos usar nuestro setworldcoordinates Método para rescalar la ventana. Mientras lo hacemos, debemos hacer que la ventana se ajuste a los datos. La barra más alta corresponderá al valor máximo de datos. El ancho de la ventana deberá ser proporcional al número de barras (el número de valores de datos) donde cada uno tiene un ancho de 40. Usando esta información, podemos calcular la coordenada sistema que tiene sentido para el conjunto de datos. Para que se vea bien, agregaremos un borde de 10 unidades alrededor de las barras.

Aquí está el programa completo. Pruébelo y luego cambie los datos para ver que puede adaptarse a los nuevos valores. Tenga en cuenta también que Hemos almacenado los valores de datos en una lista y utilizamos algunas funciones de lista. Tendremos mucho más que decir sobre las listas en un capítulo posterior.

>>import turtle

>>def drawBar(t, height):
    """ Get turtle t to draw one bar, of height. """
>>    t.begin_fill()               # start filling this shape
>>    t.left(90)
>>    t.forward(height)
>>    t.write(str(height))
>>    t.right(90)
>>    t.forward(40)
>>    t.right(90)
>>    t.forward(height)
>>    t.left(90)
>>    t.end_fill()                 # stop filling this shape



>>xs = [48, 117, 200, 240, 160, 260, 220]  # here is the data
>>maxheight = max(xs)
>>numbars = len(xs)
>>border = 10

>>wn = turtle.Screen()             # Set up the window and its attributes
>>wn.setworldcoordinates(0-border, 0-border, 40*numbars+border, maxheight+border)
>>wn.bgcolor("lightgreen")

>>tess = turtle.Turtle()           # create tess and set some attributes
>>tess.color("blue")
>>tess.fillcolor("red")
>>tess.pensize(3)



>>for a in xs:
>>    drawBar(tess, a)

>>wn.exitonclick()


 PPI: La salida del código anterior es la siguiente:

 

Este código es bastante conciso, pero cada etiqueta de altura está parcialmente cubierta por la parte superior segmento de su bar. ¿Puedes modificar el drawBar código, moviendo ligeramente la etiqueta ¿Pero no cambiar la barra? Sugerencia: la etiqueta no se puede dibujar durante la secuencia de relleno de polígono.




viernes, 18 de abril de 2025

Thinkcspy. Funciones / 6.10 Composición

 

6.10. Composition

Como ya hemos visto, puede llamar a una función desde otra. Esta capacidad de construir funciones mediante el uso de otras funciones se llama composición.

Como ejemplo, escribiremos una función que toma dos puntos, el centro del Círculo y un punto en el perímetro y calcula el área del círculo.

Suponga que el punto central se almacena en las variables xcy yc, y El punto perimetral está en xpy yp. El primer paso es encontrar el Radio del círculo, que es la distancia entre los dos puntos. Afortunadamente, acabamos de escribir una función, distance, eso hace exactamente eso, Así que ahora todo lo que tenemos que hacer es usarlo:

radius = distance(xc, yc, xp, yp)

El segundo paso es encontrar el área de un círculo con ese radio y devolverlo. Nuevamente usaremos una de nuestras funciones anteriores:

result = area(radius)
return result

Envolviendo eso en una función, obtenemos: 

>>def distance(x1, y1, x2, y2):
>>        dx = x2 - x1
>>        dy = y2 - y1
>>        dsquared = dx**2 + dy**2
>>        result = dsquared**0.5
>>        return result

>>def area(radius):
>>    b = 3.14159 * radius**2
>>    return b

>>def area2(xc, yc, xp, yp):
>>    radius = distance(xc, yc, xp, yp)
>>    result = area(radius)
>>    return result

>>print(area2(0,0,1,1))

Llamamos a esta función area2 para distinguirlo del area función definido anteriormente. Solo puede haber una función con un nombre de pila dentro de un módulo.

Tenga en cuenta que podríamos haber escrito la composición sin almacenar los resultados intermedios.

>>def area2(xc, yc, xp, yp):
>>    return area(distance(xc, yc, xp, yp))


Thinkcspy. Funciones / 6.9 Desarrollo del programa

 

6.9. Desarrollo del programa

En este punto, debería poder mirar las funciones completas y decir qué lo hacen. Además, si ha estado haciendo los ejercicios, ha escrito algunos Pequeñas funciones. Mientras escribe funciones más grandes, puede comenzar a tener más Dificultad, especialmente con tiempo de ejecución y errores semánticos.

Para lidiar con programas cada vez más complejos, vamos a sugerir una técnica llamado desarrollo incremental . El objetivo del desarrollo incremental es Evite las largas sesiones de depuración agregando y probando solo una pequeña cantidad de código a la vez.

Como ejemplo, suponga que desea encontrar la distancia entre dos puntos, dada por las coordenadas (x 1 , y 1 ) y (x 2 , y 2 ). Por el teorema pitagórico, la distancia es:

Fórmula de distancia

El primer paso es considerar qué distance la función debería parecer en Pitón. En otras palabras, ¿cuáles son las entradas (parámetros) y cuál es la salida? (Valor de retorno)?

En este caso, los dos puntos son las entradas, que podemos representar usando cuatro parámetros. El valor de retorno es la distancia, que es un valor de punto flotante.

Ya podemos escribir un esquema de la función que captura nuestro pensamiento hasta ahora. 

 

>>def distance(x1, y1, x2, y2):
>>    return 0.0
 

Obviamente, esta versión de la función no calcula distancias; siempre Devuelve cero. Pero es sintácticamente correcto, y se ejecutará, lo que significa que podemos probarlo antes de hacerlo más complicado.

Importamos el módulo de prueba para permitirnos escribir una prueba unitaria para la función. 

>>import test
>>def distance(x1, y1, x2, y2):
>>    return 0.0

>>test.testEqual(distance(1, 2, 1, 2), 0)

 

 

El testEqual La función del módulo de prueba llama a la función de distancia con entradas de muestra: (1,2, 1,2). Los primeros 1,2 son las coordenadas del primer punto y el segundo 1,2 son las coordenadas del segundo punto. ¿Cuál es la distancia entre estos dos puntos? Cero. testEqual compara lo que devuelve la función de distancia y el 0 (la respuesta correcta).

Extender el programa ...

En la línea 6, escriba otra prueba unitaria. Use (1,2, 4,6) como parámetros a la función de distancia. ¿Qué tan separados están estos dos puntos? Use ese valor (en lugar de 0) como la respuesta correcta para esta prueba unitaria.

En la línea 7, escriba otra prueba unitaria. Use (0,0, 1,1) como parámetros a la función de distancia. ¿Qué tan separados están estos dos puntos? Use ese valor como la respuesta correcta para esta prueba unitaria.

La primera prueba pasa, pero las otras fallan ya que la función de distancia aún no contiene todos los pasos necesarios.

Al probar una función, es esencial conocer la respuesta correcta.

Para la segunda prueba, la distancia horizontal es igual a 3 y la vertical La distancia es igual a 4; De esa manera, el resultado es 5 (la hipotenusa de un 3-4-5 triángulo). Para la tercera prueba, tenemos un triángulo de 1-1-SQRT (2).

En este punto hemos confirmado que la función es sintácticamente correcta y Podemos comenzar a agregar líneas de código. Después de cada cambio incremental, probamos el funcionar nuevamente. Si se produce un error en algún momento, sabemos dónde debe estar, en La última línea que agregamos.

Un primer paso lógico en el cálculo es encontrar las diferencias x 2 - x 1 e y 2 - y 1 . Almacenaremos esos valores en variables temporales nombradas dxy dy

>>def distance(x1, y1, x2, y2):
>>    dx = x2 - x1
>>    dy = y2 - y1
>>    return 0.0

A continuación, calculamos la suma de cuadrados de dxy dy

>>def distance(x1, y1, x2, y2):
>>    dx = x2 - x1
>>    dy = y2 - y1
>>    dsquared = dx**2 + dy**2
>>    return 0.0

 

Nuevamente, podríamos ejecutar el programa en esta etapa y verificar el valor de dsquared (cual debería ser 25).

Finalmente, usando el exponente fraccional 0.5 para encontrar la raíz cuadrada, Calculamos y devolvemos el resultado. 

>>import test
>>def distance(x1, y1, x2, y2):
>>    dx = x2 - x1
>>    dy = y2 - y1
>>    dsquared = dx**2 + dy**2
>>    result = dsquared**0.5
>>    return result

>>test.testEqual(distance(1,2, 1,2), 0)
>>test.testEqual(distance(1,2, 4,6), 5)
>>test.testEqual(distance(0,0, 1,1), 1.41)

 

 

Corrige el error ...

Dos de las pruebas pasan pero la última falla. ¿Todavía hay un error en la función?

Con frecuencia descubrimos errores en las funciones que estamos escribiendo. Sin embargo, es posible que haya un error en una prueba. Aquí el error está en la precisión de la respuesta correcta.

La tercera prueba falla porque, por defecto, prueba TestEqual 5 dígitos a la derecha del punto decimal.

  • Cambiar 1.41a 1.41421 y correr. La prueba pasará.

Hay circunstancias en las que 2 dígitos a la derecha del punto decimal son suficientemente precisos.

  • Copiar línea 11 en la línea 12. En línea 12, cambiar 1.41421a 1.41. Correr. La prueba falla.

  • Tipo , 2 después de 1.41. (El 2 representa la precisión de la prueba: cuántos dígitos a la derecha del decimal debe ser correcto).

¡Ahora las cuatro pruebas pasan! ¡Maravilloso! Sin embargo, es posible que aún necesite realizar pruebas adicionales.

Cuando comience, puede agregar solo una línea o dos de código a la vez. Como tú Obtenga más experiencia, puede encontrarse escribiendo y depurando más grande trozos conceptuales. A medida que mejora sus habilidades de programación, debe encontrarse Gestión de trozos más grandes y más grandes: esto es muy similar a la forma en que aprendimos a leer letras, sílabas, palabras, frases, oraciones, párrafos, etc., o la forma en que aprendemos Para fragmentar la música: desde notas indviduales hasta acordes, bares, frases, etc.

Los aspectos clave del proceso son:

  1. Asegúrese de saber lo que está tratando de lograr. Entonces puede escribir pruebas unitarias apropiadas.

  2. Comience con un programa de esqueleto que funcione y haga pequeños cambios incrementales. En cualquier Punto, si hay un error, sabrá exactamente dónde está.

  3. Use variables temporales para contener valores intermedios para que pueda inspeccionar fácilmente y revisarlos.

  4. Una vez que el programa esté funcionando, es posible que desee consolidar múltiples declaraciones en expresiones compuestas, Pero solo haga esto si no hace que el programa sea más difícil de leer.

CLcoding. Pregunta y respuesta

 

What will the following Python code output?

>>arr = [1, 3, 5, 7, 9]
>>res = arr[::-1][::2]
>>print(res)

Options:
[9, 7, 5, 3, 1]
[9, 5, 1]
[1, 5, 9]
[3, 7, 9]

En google colab 
>>arr=[1,3,5,7,9]
>>res=arr[::-1][::2]
>>print(res)
 
>>>
[9, 5, 1]

Respuesta :

Paso 1: Comprensión ARR [::-1]

La sintaxis de corte [::-1] invierte la matriz.

  • Matriz original : [1, 3, 5, 7, 9]
  • Matriz invertida : [9, 7, 5, 3, 1]

Entonces, después de la primera porción (arr [::-1]), la matriz se convierte en:
[9, 7, 5, 3, 1]


Paso 2: Comprensión [:: 2]

Ahora, tomamos la matriz inversa y aplicamos el corte [:: 2].

El corte [:: 2] significa:

  • Comience desde el comienzo de la matriz.
  • Tome cada segundo elemento (tamaño de paso = 2).

Para la matriz inversa [9, 7, 5, 3, 1]:

  • Primer elemento: 9 (índice 0)
  • Omita un elemento (7) y tome 5 (índice 2).
  • Omita un elemento más (3) y tome 1 (índice 4).

Resultado después de [:: 2]: [9, 5, 1]


Paso 3: almacenar el resultado en RES

El resultado final del corte combinado se almacena en RES:
Res = [9, 5, 1]


Paso 4: Impresión del resultado

Cuando imprime RES, la salida es:

[ 9, 5, 1 ]

Puntos clave :

  1. [::-1] invierte la matriz.
  2. [:: 2] selecciona cada segundo elemento de la matriz inversa.
  3. La combinación de rodajas proporciona el resultado deseado [9, 5, 1].
 
 

 

Python Coding Challange - Question with Answer (01180425)

  


>>for i in range(0,-2,-2): # Bucle o ciclo for vi: 0; decrementos -2; vf: -2
>>  print(i)
 
 

Parámetros de rango (inicio, detener, paso):

  • inicio = 0 → donde comienza la secuencia

  • parar = -2 la secuencia se detiene (pero este valor no está incluido )

  • paso = -2 → paso (bajando por 2)

¿Qué pasa aquí?

Este rango (0, -2, -2) genera una secuencia que comienza en 0 y se mueve hacia atrás 

en pasos de -2, deteniéndose antes de -2 .

Entonces produce:

[ 0 ]

Porque:

  • 0 está incluido ✔️

  • El siguiente valor sería -2, pero el rango excluye el valor de parada, por lo que

    no está incluido ❌

Producción:

0

Resumen:

Este bucle se ejecuta solo una vez , imprimiendo 0.


Thinkcspy. Funciones / 6.8 Usando una funcion principal

 

6.8. Usando una función principal

Usar funciones es una buena idea. Nos ayuda a modularizar nuestro código rompiendo un programa en partes lógicas donde cada parte es responsable de una tarea específica. Por ejemplo, en uno de nuestros primeros programas allí fue una función llamada drawSquare Eso fue responsable de hacer que una tortuga dibujara un cuadrado de algún tamaño. La tortuga real y el tamaño real del cuadrado se definieron para proporcionar como parámetros. Aquí está ese programa original. 

>>import turtle

>>def drawSquare(t, sz):
>>    """Make turtle t draw a square of with side sz."""

>>    for i in range(4):
>>        t.forward(sz)
>>        t.left(90)


>>wn = turtle.Screen()          # Set up the window and its attributes
>>wn.bgcolor("lightgreen")

>>alex = turtle.Turtle()        # create alex
>>drawSquare(alex, 50)          # Call the function to draw the square

>>wn.exitonclick()

Si observa de cerca la estructura de este programa, notará que primero realizamos todos nuestros necesarios import declaraciones, en este caso para poder usar el turtle módulo. A continuación, definimos la función drawSquare. En este punto, podríamos haber definido tantas funciones como se necesitaran. Finalmente, hay cinco declaraciones que configuran la ventana, crean la tortuga, realizan la invocación de funciones y esperen a que un usuario haga clic para finalizar el programa.

Estas cinco declaraciones finales realizan el procesamiento principal que hará el programa. Observe que gran parte del detalle ha sido empujado dentro del drawSquare función. Sin embargo, todavía hay estas cinco líneas de código que se necesitan para hacer las cosas.

En muchos lenguajes de programación (por ejemplo, Java y C ++), no es posible simplemente tener declaraciones sentadas solas así en la parte inferior del programa. Deben ser parte de una función especial que es invoca automáticamente por el sistema operativo cuando se ejecuta el programa. Esta función especial se llama principal. Aunque el lenguaje de programación de Python no requiere esto, en realidad es una buena idea que podemos incorporar a la estructura lógica de nuestro programa. En otras palabras, estas cinco líneas están lógicamente relacionadas entre sí, ya que proporcionan las tareas principales que el programa realizará. Dado que las funciones están diseñadas para permitirnos dividir un programa en piezas lógicas, tiene sentido llamar a esta pieza main.

El siguiente Activecode muestra esta idea. En la línea 11 hemos definido una nueva función llamada main Eso no necesita ningún parámetro. Las cinco líneas de procesamiento principal ahora se colocan dentro de esta función. Finalmente, para ejecutar ese código de procesamiento principal, necesitamos invocar el main función (línea 20). Cuando presione la ejecución, verá que el programa funciona igual que antes. 

import turtle

def drawSquare(t, sz):
    """Make turtle t draw a square of with side sz."""

    for i in range(4):
        t.forward(sz)
        t.left(90)


def main():                      # Define the main function
    wn = turtle.Screen()         # Set up the window and its attributes
    wn.bgcolor("lightgreen")

    alex = turtle.Turtle()       # create alex
    drawSquare(alex, 50)         # Call the function to draw the square

    wn.exitonclick()

main()                           # Invoke the main function


Ahora nuestra estructura del programa es la siguiente. Primero, importe cualquier módulo que sea requerido. En segundo lugar, defina cualquier función que sea necesaria. Tercero, defina un main función que se inicie el proceso. Y finalmente, invoque la función principal (que a su vez llamará a las otras funciones según sea necesario).

Nota

En Python no hay nada especial en el nombre main. Podríamos haber llamado a esta función todo lo que quisiéramos. Elegimos main Solo para ser consistente con algunos de los otros idiomas.

Tema avanzado

Antes de que el intérprete de Python ejecute su programa, define algunas variables especiales. Una de esas variables se llama __name__ y se establece automáticamente en el valor de cadena "__main__" Cuando el programa se ejecuta solo de manera independiente. Por otro lado, si el programa está siendo importado por otro programa, entonces el __name__ La variable se establece en el nombre de ese módulo. Esto significa que podemos saber si el programa se está ejecutando solo o si está siendo utilizado por otro programa y, según esa observación, podemos o no elegir ejecutar parte del código que hemos escrito.

Por ejemplo, suponga que hemos escrito una colección de funciones para hacer algunas matemáticas simples. Podemos incluir un main función para invocar estas funciones matemáticas. Sin embargo, es mucho más probable que estas funciones sean importadas por otro programa para otro propósito. En ese caso, no querríamos ejecutar nuestra función principal.

El ActiveCode a continuación define dos funciones simples y una principal.

def squareit(n):
    return n * n

def cubeit(n):
    return n*n*n

def main():
    anum = int(input("Please enter a number"))
    print(squareit(anum))
    print(cubeit(anum))

if __name__ == "__main__":
    main()


La línea 12 usa un if declaración para preguntar sobre el valor del __name__ variable. Si el valor es "__main__", entonces el main se llamará a la función. De lo contrario, se puede suponer que el programa se está importando a otro programa y no queremos llamar main Porque ese programa invocará las funciones según sea necesario. Esta capacidad de ejecutar condicionalmente nuestra función principal puede ser extremadamente útil cuando estamos escribiendo código que potencialmente serán utilizados por otros. Nos permite incluir la funcionalidad que el usuario del código no necesitará, con mayor frecuencia como parte de un proceso de prueba para asegurarnos de que las funciones funcionen correctamente.

Nota

Para ejecutar condicionalmente el main función, utilizamos una estructura llamada if Declaración para crear lo que se conoce como selección. Este tema se estudiará con mucho más detalle más adelante.

Entradas recientes

Sabes que es SfePy y para que sirve?

 Fuente: SfePy.org SfePy: elementos finitos simples en Python ¶ SfePy es un software para resolver sistemas de diferencial parcial acoplado ...

Entradas Populares