Diferència entre revisions de la pàgina «ASIX-M3-UF2-A1»

De wikiserver
Dreceres ràpides: navegació, cerca
 
(25 revisions intermèdies per 2 usuaris que no es mostren)
Línia 1: Línia 1:
'''Programació Modular i Paquets en Python'''
+
==Descomposició funcional==
 +
 
 +
:*L’objectiu serà resoldre el problema general com a una suma de subproblemes més petits.
 +
 
 +
:*La solució a cada subproblema s’anomena subrutina o subprograma, i a Java, mètode.
 +
 
 +
:*Permet la reutilització del codi, facilita la seva lectura i el seu manteniment.
 +
 
 +
:*Escriure codi més genèric facilita la seva reutilització.
 +
 
 +
'''Disseny descendent'''
 +
 
 +
:*El mètode del disseny descendent consisteix en descompondre el problema a resoldre en altres més senzills. A aquests se'ls aplica el mateix procediment fins arribar a problemes prou petits que podem resoldre directament.
 +
 
 +
:*Refinament de l’algorisme (stepwise refinement) és com es coneix aquest procediment de descomposició.
 +
 
 +
:*Representació en forma d'arbre:
 +
 
 +
::- Cada node és un mòdul, o problema, o solució hipotètica.
 +
::- Cada subarbre depenent d'aquest node es fa servir per a la resolució d'aquest subproblema.
 +
::- El node del nivell més alt és el problema de partida.
 +
::- L’algorisme serà correcte si la solució que es dóna a cada nivell ho és.
 +
::- El programa es pot construir de sota a dalt creant primer procediments que resolguin els mòduls de detall que, un cop comprovats seran utilitzats per altres procediments més generals fins a arribar a la creació del programa.
 +
 
 +
[[Imatge:m3uf2_disseny_modular_1.png |600px|center| Disseny modular]]
 +
 
 +
==Reutilització de subproblemes resolts==
 +
 
 +
:*La descomposició mitjançant disseny descendent permet reaprofitar la solució de subproblemes idèntics, o força semblants.
 +
 
 +
:*Qualsevol subproblema d’un nivell donat pot ser part de qualsevol subproblema d’un nivell superior. Per remarcar
 +
 
 +
[[Imatge:m3uf2_disseny_modular_2.png |600px|center| Disseny modular]]
 +
 
 +
:*En descompondre un problema, s'ha d'intentar fer-ho de manera que es forci l’aparició de subproblemes repetits, i així la seva resolució es pot reaprofitar en diversos llocs.
 +
 
 +
==Aplicació correcta del disseny descendent==
 +
 
 +
Diferents persones poden arribar a conclusions diferents sobre com dur a terme la descomposició. Entre totes les solucions diferents possibles, algunes es poden considerar millors que d’altres. De fet, res impedeix, partir d'una solució concreta i aplicar refinaments que la millorin.
 +
 
 +
Criteris per a l'avaluació de la descomposició:
 +
 
 +
:*Si un problema que sembla a priori força complex es descompon en molts pocs nivells, potser val la pena fer una segona ullada. Inversament, si un problema no massa complex té massa nivells, potser s’ha anat massa lluny en la descomposició.
 +
 
 +
:*Veure si el nombre de passes incloses a cadascun dels subproblemes no és excessivament gran i és fàcil de seguir i entendre. En cas contrari, potser encara faria falta aplicar nous nivells de descomposició.
 +
 
 +
:*Repassar que els noms assignats als subproblemes siguin autoexplicatius i expressin clarament la tasca que estan resolent. Sense ni tan sols llegir les seves passes, caldria entendre perfectament què s’assoleix en resoldre’ls. En cas contrari, potser la descomposició no està agrupant conjunts de passes realment relacionades entre elles.
 +
 
 +
:*Si absolutament cap dels subproblemes és reutilitzat enlloc, especialment en descomposicions en molts nivells, és molt possible que no s’hagi triat correctament la manera de descompondre alguns subproblemes.
 +
 
 +
:*Vinculat al punt anterior, l’aparició de subproblemes molt semblants o idèntics, però tractats per separat en diferents llocs, també sol ser indici que no s’està aplicant la capacitat de reutilitzar subproblemes correctament.
 +
 
 +
==Programació modular==
  
 
La programació modular consisteix en dividir un programa gran i/o complex en subprogrames més petits o simples, aconseguint fer-lo més comprensible i manejable. Per això, s'implementen funcions, classes i mòduls.
 
La programació modular consisteix en dividir un programa gran i/o complex en subprogrames més petits o simples, aconseguint fer-lo més comprensible i manejable. Per això, s'implementen funcions, classes i mòduls.
Línia 10: Línia 62:
 
:* Pot rebre zero o més arguments com a entrada.
 
:* Pot rebre zero o més arguments com a entrada.
 
:* Por retornar un valor i/o realitzar una tasca.
 
:* Por retornar un valor i/o realitzar una tasca.
:* L'us de funcions permet fer una programació estructurada:
+
:* L'ús de funcions permet fer una programació estructurada:
 
::* modularització: segmentar un programa complex en mòduls més simples facilitant la programació i la depuració.
 
::* modularització: segmentar un programa complex en mòduls més simples facilitant la programació i la depuració.
 
::* reutilització: una mateixa funció es pot utilitzar des de diferents punts d'un programa i també des de diferents programes.
 
::* reutilització: una mateixa funció es pot utilitzar des de diferents punts d'un programa i també des de diferents programes.
Línia 22: Línia 74:
 
     return value
 
     return value
 
</source>
 
</source>
 +
 
:* Els arguments es passen per valor: si canvien el seu valor dins de la funció, no canvien "a fora".
 
:* Els arguments es passen per valor: si canvien el seu valor dins de la funció, no canvien "a fora".
 
:* Per modificar variable no locals a la funció, cal definir-les com a globals en la primera línia.
 
:* Per modificar variable no locals a la funció, cal definir-les com a globals en la primera línia.
Línia 40: Línia 93:
  
  
:'''Mòduls'''
+
'''Example function'''
  
[https://pythones.net/modularidad-en-python/ Moduls]
+
<source lang="python">
 +
def saludo(primer_nombre,apellido):
 +
    print(f"Hola, {primer_nombre} {apellido}")
 +
   
  
[https://docs.python.org/es/3.8/tutorial/modules.html __init__]
+
saludo("Timmy","Jones",34)
  
:* Un mòdul és un arxiu amb un codi independent i una determinada funcionalitat.
 
:* Pot ser utilitzat per qualsevol aplicació.
 
:* Es poden utilitzar mòduls propis de python, de tercers o propis.
 
:* Conté funcions, classes, definicions, ...
 
:* Per poder utilitzar un mòdul s'ha d'importar prèviament.
 
<source lang="python">
 
import modul    # 'modul': nom del mòdul a importar
 
</source>
 
:* Si volem importar només algunes parts del mòdul:
 
<source lang="python">
 
from modul import funcio_1, funcio_2  # 'funcio_x': funcions del mòdul.
 
 
</source>
 
</source>
  
:'''Paquets'''
+
'''un altre'''
:* S'utilitza per organitzar els mòduls.
 
:* Pot contenir mòduls i altres paquets.
 
:* Per tractar un directori com a paquet cal que contingui el fitxer __init.py__
 
:* __init.py__ pot:
 
::* estar buit.
 
::* contenir codi d'inicialització del paquet.
 
::* contenir el conjunt de variables __ALL__.
 
  
<pre>
+
<source lang="python">
jocCombat /
+
def saludo(primer_nombre,apellido):
|-__init__.py
+
     print(f"Hola, {primer_nombre} {apellido}")
|-regles /
+
      
     |-__init__.py
 
     |-monedes.py
 
    |-lluitador.py
 
    |-bestiari.py
 
    |-combat.py
 
|-interficie /
 
    |-__init__.py
 
    |-entradaTeclat.py
 
    |-sortidaPantalla.py
 
</pre>
 
  
:* Es poden importar submòduls individualment:
+
saludo("Timmy","Jones")
<source lang="python">
 
>>>import jocCombat.regles.lluitador                # Càrrega el mòdul lluitador
 
>>>jocCombat.regles.lluitador.danyar(lluitador, 2) # Cal fer referència al nom complert
 
 
</source>
 
</source>
  
:* Es pot importar el submòul:
+
'''un altre més'''
<source lang="python">
 
>>>from jocCombat.regles import lluitador          # Càrrega el mòdul lluitador
 
>>>lluitador.danyar(lluitador, 2)                  # No cal utilitzar el prefix del paquet
 
</source>
 
  
:* Es poden només les funcions que necessitem:
 
:* Es pot importar el submòul:
 
 
<source lang="python">
 
<source lang="python">
>>>from jocCombat.regles.lluitador import danyar    # Càrrega la funció lluitador
+
def myFun(arg1, *argv):
>>>danyar(lluitador, 2)                             # Utilitzem directament la funció
+
print("First argument :", arg1)
</source>
+
for arg in argv:
 +
print("Next argument through *argv :", arg)
  
:*La forma from jocCombat import * importaria tots els submòduls:
 
::* En general, no és recomanable.
 
::* Pot ser massa lent.
 
::* Pot tenir efectes no dessitjats.
 
  
 +
myFun('Hello', 'Welcome', 'to', 'M03')
  
 +
</source>
  
Ahora, ¿qué sucede cuando el usuario escribe from sound.effects import *? Idealmente, uno esperaría que esto de alguna manera vaya al sistema de archivos, encuentre cuales submódulos están presentes en el paquete, y los importe a todos. Esto puede tardar mucho y el importar sub-módulos puede tener efectos secundarios no deseados que sólo deberían ocurrir cuando se importe explícitamente el sub-módulo.
 
  
La única solución es que el autor del paquete provea un índice explícito del paquete. La declaración import usa la siguiente convención: si el código del __init__.py de un paquete define una lista llamada __all__, se toma como la lista de los nombres de módulos que deberían ser importados cuando se hace from package import *. Es tarea del autor del paquete mantener actualizada esta lista cuando se libera una nueva versión del paquete. Los autores de paquetes podrían decidir no soportarlo, si no ven un uso para importar * en sus paquetes. Por ejemplo, el archivo sound/effects/__init__.py podría contener el siguiente código:
+
'''Ejemplo de llamada a una función, con return de varios parámetros y recogida en diferentes variables.'''
  
__all__ = ["echo", "surround", "reverse"]
+
<source lang="python">
  
Esto significaría que from sound.effects import * importaría esos tres submódulos del paquete sound.
+
def aHsMinSeg (x):
 +
    '''''Dada una duración en segundos sin fracciones (la función debe
 +
    invocarse con números enteros) se la convierte a horas, minutos y segundos'''''
 +
    hs = x / 3600
 +
    min = (x % 3600) / 60
 +
    seg = (x % 3600 ) % 60
 +
    return (hs, min, seg)
 +
    '''''Llamada a función'''''
 +
(h, m, s) = aHsMinSeg(3661)
 +
print ("Resultado: ",h,"horas",m,"minutos",s,"segundos")
  
Si no se define __all__, la declaración from sound.effects import * no importa todos los submódulos del paquete sound.effects al espacio de nombres actual; sólo se asegura que se haya importado el paquete sound.effects (posiblemente ejecutando algún código de inicialización que haya en __init__.py) y luego importa aquellos nombres que estén definidos en el paquete. Esto incluye cualquier nombre definido (y submódulos explícitamente cargados) por __init__.py. También incluye cualquier submódulo del paquete que pudiera haber sido explícitamente cargado por declaraciones import previas. Considere este código:
+
</source>
  
import sound.effects.echo
+
[[https://j2logo.com/args-y-kwargs-en-python/ funcions amb número indeterminat de paràmetres]]
import sound.effects.surround
 
from sound.effects import *
 
  
En este ejemplo, los módulos echo y surround se importan en el espacio de nombre actual porque están definidos en el paquete sound.effects cuando se ejecuta la declaración from...import. (Esto también funciona cuando se define __all__).
+
:'''Mòduls'''
  
A pesar de que ciertos módulos están diseñados para exportar solo nombres que siguen ciertos patrones cuando uses import *, también se considera una mala práctica en código de producción.
+
[https://pythones.net/modularidad-en-python/ Moduls]
  
Recuerda, ¡no hay nada malo al usar from package import specific_submodule! De hecho, esta es la notación recomendada a menos que el módulo que importamos necesite usar submódulos con el mismo nombre desde un paquete diferente.
+
[https://docs.python.org/es/3.8/tutorial/modules.html __init__]
  
 +
:* Un mòdul és un arxiu amb un codi independent i una determinada funcionalitat.
 +
:* Pot ser utilitzat per qualsevol aplicació.
 +
:* Es poden utilitzar mòduls propis de python, de tercers o propis.
 +
:* Conté funcions, classes, definicions, ...
 +
:* Per poder utilitzar un mòdul s'ha d'importar prèviament.
 +
<source lang="python">
 +
import modul    # 'modul': nom del mòdul a importar
 +
</source>
 +
:* Si volem importar només algunes parts del mòdul:
 +
<source lang="python">
 +
from modul import funcio_1, funcio_2  # 'funcio_x': funcions del mòdul.
 +
</source>
  
Un ejemplo claro es el módulo “math” por ejemplo que en su código incluye varias operaciones matemáticas que podemos llamar como una función luego de importar el módulo. Y no solo eso, podemos crear nuestros propios módulos para utilizarlos en nuestros proyectos cuando sea necesario. Así por ejemplo tu puedes crearte un módulo que muestre un menú en consola, y cuando necesites utilizarlo en un proyecto simplemente lo importas y lo utilizas, variando en cada proyecto los ítems del mismo, pero  sin necesidad de crear nuevamente todo el algoritmo y código que implica presentar ese menú.
+
==Diagrames de flux==
 
 
Por ello la modularidad en python está ligada también a la funcionalidad (funciones). Así utilizando todas estas propiedades del paradigma orientado a objetos logramos reducir mucho la cantidad de líneas de código que debemos escribir y evitamos la redundancia de código (escribir varias veces el mismo código) como ya explicamos en funciones en python!
 
 
 
 
 
 
 
 
 
Un módulo es un objeto que sirve como unidad para organizar el código de un proyecto desarrollado en Python. Los módulos tienen en su contenido los objetos (funciones, clases, definiciones, etc) que se definan en él. Para utilizar el contenido de un módulo es necesario importarlo.
 
'''
 
Importar módulos en Python'''
 
 
 
Para que el contenido de un módulo esté disponible en otro, es necesario importarlo. La forma mas utilizada para importar en Python es con la palabra reservada import.
 
 
 
import modulo    # En 'modulo' se escribe el nombre del módulo que vaya a ser importado
 
 
 
Es necesario que, en el directorio del módulo, se encuentre un archivo llamado ‘__init__.py’. Este es necesario para que Python trate los directorios que contienen los archivos como paquetes. Esto previene que los directorios con nombres comunes, como ‘string’, oculten involuntariamente los módulos válidos que aparecen más adelante en la ruta de búsqueda del módulo. En el peor de los casos, ‘__init__.py’ puede estar vacío.
 
 
 
Un Paquete es una estructura de organización de Python que contiene módulos y otros paquetes.
 
'''
 
‘from’'''
 
 
 
‘from’ es una palabra reservada que es utilizada en conjunto con ‘import’ para importar partes específicas de un paquete o módulo.
 
 
 
from time import Time  # Importa la función 'Time' del módulo 'time'
 
'''
 
Contenido de los Módulos en Python'''
 
 
 
En el caso de importar un modulo real, la salida sería la siguiente (se importará y mostrará el módulo ‘pygame’ y su contenido):
 
 
 
['ACTIVEEVENT', 'ANYFORMAT', 'ASYNCBLIT', 'AUDIODEVICEADDED', 'AUDIODEVICEREMOVED', 'AUDIO_ALLOW_ANY_CHANGE', 'AUDIO_ALLOW_CHANNELS_CHANGE', 'AUDIO_ALLOW_FORMAT_CHANGE', 'AUDIO_ALLOW_FREQUENCY_CHANGE', 'AUDIO_S16', 'AUDIO_S16LSB', 'AUDIO_S16MSB', 'AUDIO_S16SYS', 'AUDIO_S8', 'AUDIO_U16', 'AUDIO_U16LSB', 'AUDIO_U16MSB', 'AUDIO_U16SYS', 'AUDIO_U8', 'BIG_ENDIAN', 'BLEND_ADD', 'BLEND_MAX', 'BLEND_MIN', 'BLEND_MULT', 'BLEND_PREMULTIPLIED', 'BLEND_RGBA_ADD', 'BLEND_RGBA_MAX', 'BLEND_RGBA_MIN', 'BLEND_RGBA_MULT', 'BLEND_RGBA_SUB', 'BLEND_RGB_ADD', 'BLEND_RGB_MAX', 'BLEND_RGB_MIN', 'BLEND_RGB_MULT', 'BLEND_RGB_SUB', 'BLEND_SUB', 'BUTTON_LEFT', 'BUTTON_MIDDLE', 'BUTTON_RIGHT', 'BUTTON_WHEELDOWN', 'BUTTON_WHEELUP', 'BUTTON_X1', 'BUTTON_X2', 'BufferError', 'BufferProxy', 'Color', 'DOUBLEBUF', 'DROPBEGIN', 'DROPCOMPLETE', 'DROPFILE', 'DROPTEXT', 'FINGERDOWN', 'FINGERMOTION', 'FINGERUP', 'FULLSCREEN', 'GL_ACCELERATED_VISUAL', 'GL_ACCUM_ALPHA_SIZE', 'GL_ACCUM_BLUE_SIZE', 'GL_ACCUM_GREEN_SIZE', 'GL_ACCUM_RED_SIZE', 'GL_ALPHA_SIZE', 'GL_BLUE_SIZE', 'GL_BUFFER_SIZE', 'GL_DEPTH_SIZE', 'GL_DOUBLEBUFFER', 'GL_GREEN_SIZE', 'GL_MULTISAMPLEBUFFERS', 'GL_MULTISAMPLESAMPLES', 'GL_RED_SIZE', 'GL_STENCIL_SIZE', 'GL_STEREO', 'GL_SWAP_CONTROL', 'HAT_CENTERED', 'HAT_DOWN', 'HAT_LEFT', 'HAT_LEFTDOWN', 'HAT_LEFTUP', 'HAT_RIGHT', 'HAT_RIGHTDOWN', 'HAT_RIGHTUP', 'HAT_UP', 'HAVE_NEWBUF', 'HWACCEL', 'HWPALETTE', 'HWSURFACE', 'IYUV_OVERLAY', 'JOYAXISMOTION', 'JOYBALLMOTION', 'JOYBUTTONDOWN', 'JOYBUTTONUP', 'JOYHATMOTION', 'KEYDOWN', 'KEYUP', 'KMOD_ALT', 'KMOD_CAPS', 'KMOD_CTRL', 'KMOD_LALT', 'KMOD_LCTRL', 'KMOD_LMETA', 'KMOD_LSHIFT', 'KMOD_META', 'KMOD_MODE', 'KMOD_NONE', 'KMOD_NUM', 'KMOD_RALT', 'KMOD_RCTRL', 'KMOD_RMETA', 'KMOD_RSHIFT', 'KMOD_SHIFT', 'K_0', 'K_1', 'K_2', 'K_3', 'K_4', 'K_5', 'K_6', 'K_7', 'K_8', 'K_9', 'K_AMPERSAND', 'K_ASTERISK', 'K_AT', 'K_BACKQUOTE', 'K_BACKSLASH', 'K_BACKSPACE', 'K_BREAK', 'K_CAPSLOCK', 'K_CARET', 'K_CLEAR', 'K_COLON', 'K_COMMA', 'K_DELETE', 'K_DOLLAR', 'K_DOWN', 'K_END', 'K_EQUALS', 'K_ESCAPE', 'K_EURO', 'K_EXCLAIM', 'K_F1', 'K_F10', 'K_F11', 'K_F12', 'K_F13', 'K_F14', 'K_F15', 'K_F2', 'K_F3', 'K_F4', 'K_F5', 'K_F6', 'K_F7', 'K_F8', 'K_F9', 'K_FIRST', 'K_GREATER', 'K_HASH', 'K_HELP', 'K_HOME', 'K_INSERT', 'K_KP0', 'K_KP1', 'K_KP2', 'K_KP3', 'K_KP4', 'K_KP5', 'K_KP6', 'K_KP7', 'K_KP8', 'K_KP9', 'K_KP_DIVIDE', 'K_KP_ENTER', 'K_KP_EQUALS', 'K_KP_MINUS', 'K_KP_MULTIPLY', 'K_KP_PERIOD', 'K_KP_PLUS', 'K_LALT', 'K_LAST', 'K_LCTRL', 'K_LEFT', 'K_LEFTBRACKET', 'K_LEFTPAREN', 'K_LESS', 'K_LMETA', 'K_LSHIFT', 'K_LSUPER', 'K_MENU', 'K_MINUS', 'K_MODE', 'K_NUMLOCK', 'K_PAGEDOWN', 'K_PAGEUP', 'K_PAUSE', 'K_PERIOD', 'K_PLUS', 'K_POWER', 'K_PRINT', 'K_QUESTION', 'K_QUOTE', 'K_QUOTEDBL', 'K_RALT', 'K_RCTRL', 'K_RETURN', 'K_RIGHT', 'K_RIGHTBRACKET', 'K_RIGHTPAREN', 'K_RMETA', 'K_RSHIFT', 'K_RSUPER', 'K_SCROLLOCK', 'K_SEMICOLON', 'K_SLASH', 'K_SPACE', 'K_SYSREQ', 'K_TAB', 'K_UNDERSCORE', 'K_UNKNOWN', 'K_UP', 'K_a', 'K_b', 'K_c', 'K_d', 'K_e', 'K_f', 'K_g', 'K_h', 'K_i', 'K_j', 'K_k', 'K_l', 'K_m', 'K_n', 'K_o', 'K_p', 'K_q', 'K_r', 'K_s', 'K_t', 'K_u', 'K_v', 'K_w', 'K_x', 'K_y', 'K_z', 'LIL_ENDIAN', 'MOUSEBUTTONDOWN', 'MOUSEBUTTONUP', 'MOUSEMOTION', 'MOUSEWHEEL', 'MULTIGESTURE', 'Mask', 'NOEVENT', 'NOFRAME', 'NUMEVENTS', 'OPENGL', 'OPENGLBLIT', 'Overlay', 'PREALLOC', 'PixelArray', 'PygameVersion', 'QUIT', 'RESIZABLE', 'RLEACCEL', 'RLEACCELOK', 'Rect', 'SCRAP_BMP', 'SCRAP_CLIPBOARD', 'SCRAP_PBM', 'SCRAP_PPM', 'SCRAP_SELECTION', 'SCRAP_TEXT', 'SRCALPHA', 'SRCCOLORKEY', 'SWSURFACE', 'SYSWMEVENT', 'Surface', 'SurfaceType', 'TEXTEDITING', 'TEXTINPUT', 'TIMER_RESOLUTION', 'USEREVENT', 'USEREVENT_DROPFILE', 'UYVY_OVERLAY', 'VIDEOEXPOSE', 'VIDEORESIZE', 'Vector2', 'Vector3', 'WINDOWEVENT', 'WINDOWEVENT_CLOSE', 'YUY2_OVERLAY', 'YV12_OVERLAY', 'YVYU_OVERLAY', '__builtins__', '__cached__', '__color_constructor', '__color_reduce', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__rect_constructor', '__rect_reduce', '__spec__', '__version__', 'base', 'bufferproxy', 'cdrom', 'color', 'colordict', 'compat', 'constants', 'cursors', 'display', 'draw', 'encode_file_path', 'encode_string', 'error', 'event', 'fastevent', 'font', 'get_array_interface', 'get_error', 'get_init', 'get_sdl_byteorder', 'get_sdl_version', 'image', 'init', 'joystick', 'key', 'mask', 'math', 'mixer', 'mixer_music', 'mouse', 'movie', 'overlay', 'packager_imports', 'pixelarray', 'pixelcopy', 'quit', 'rect', 'register_quit', 'rev', 'rwobject', 'scrap', 'segfault', 'set_error', 'sndarray', 'sprite', 'surface', 'surfarray', 'sysfont', 'threads', 'time', 'transform', 'ver', 'vernum', 'version', 'warn_unwanted_files']
 
 
 
Estas son todas las funciones y variables disponibles del modulo ‘pygame‘. Cabe destacar que para cada módulo se tendrá una salida distinta.
 
'''
 
Crear un Módulo en Python'''
 
 
 
Se crea un archivo con el nombre que uno desee (el nombre se escoge generalmente según el contenido del archivo) y dentro del archivo se coloca el contenido que vaya a ser utilizado en el programa base. Por ejemplo, se creará una función para calcular la raíz cuadrada de un número y las raíces de un polinomio cuadrático en un archivo llamado “raices.py”:
 
 
 
def raizCuadrada(i):  # Función que calcula la raíz cuadrada de un número
 
  return i**(1/2)
 
def raices(a,b,c):  # Función que calcula las raíces de un polinomio cuadrático
 
  return ((-b+raiz(b**2-(4*a*c)))/(2*a)),((-b-raiz(b**2-(4*a*c)))/(2*a))
 
 
 
Se importan la funciones en el programa base de la siguiente forma:
 
 
 
import raices  # Importa el módulo 'raices'
 
A = float(input("Ingrese el coeficiente de la variable cuadrática\n"))
 
B = float(input("Ingrese el coeficiente de la variable lineal\n"))
 
C = float(input("Ingrese el término independiente\n"))
 
r1 = 0
 
r2 = 0
 
r1,r2 = raices.raices(A,B,C) # Llamado a la función 'raices' del módulo 'raices'
 
print(f"La primera raíz es: {r1}")
 
print(f"La segunda raíz es: {r2}")
 
  
Ya que se importó el módulo ‘raices’, para hacer un llamado a una función de este módulo, hay que utilizar como prefijo al nombre de la función, el nombre del modulo (raices.raices).
+
Els diagrames de flux es poden utilitzar per representar gràficament una seqüència ordenada de passos lògics per fer una tasca. Per fer aquesta representació, s'utilitzen un conjunt de símbols en els que es descriuen els passos a fer.
  
Una practica mas sencilla es importar todos los elementos pertenecientes al módulo ‘raices’ utilizando ‘from’ de la siguiente forma:
+
Abans de fer un diagrama de flux es convenient  fer un algoritme que descrigui quins són els passos a seguir per fer la tasca.
  
from raices import raices, raizCuadrada
+
:* Algoritme: Passos ordenats per fer una tasca.
  
De esta forma, los llamados a la función ‘raices’ ya no necesitan utilizar como prefijo el nombre del módulo al cual pertenecen:
+
:* Diagrama de Flux: Representació gràfica amb símbols de l'algoritme.
from raices import raices, raizCuadrada
 
  
A = float(input("Ingrese el coeficiente de la variable cuadrática\n"))
+
Un cop tenim l'algoritme / diagrama de flux, haurem de fer el programa utilitzen les ordres corresponents del llenguatge de programació emprat.
B = float(input("Ingrese el coeficiente de la variable lineal\n"))
 
C = float(input("Ingrese el término independiente\n"))
 
r1 = 0
 
r2 = 0
 
r1,r2 = raices(A,B,C) # Llamado a la función sin el prefijo del módulo
 
print(f"La primera raiz es: {r1}")
 
print(f"La segunda raiz es: {r2}")
 
'''
 
Importar desde Subdirectorios'''
 
  
Una práctica muy común a la hora de desarrollar proyectos es la de crear subdirectorios en el directorio base con funciones, clases y/u objetos que vayan a ser necesarios en el desarrollo del proyecto. Para importar estos en el proyecto base, es necesario que en el directorio principal y en el subdirectorio estén presentes los respectivos archivos ‘__init__.py’. Teniendo esto en cuenta, el proceso de importación es similar al explicado antes:
+
:* Símbols emprats:
  
Se tiene un programa que dado un numero de estudiantes, sus edades e indices académicos, calcula su promedio y lo imprime.
+
[[Imatge:m3_uf2_diagrama_flux_simbols.png |400px|center| Símbols diagrama flux]]
  
El proyecto está organizado de la siguiente forma:
+
:* Regles:
  
Proyecto /
+
::1. Tots els símbols han d'estar connectats.
|-__init__.py
 
|-promedios.py
 
|-utiles /
 
    |-__init__.py
 
    |-funciones.py
 
    |-clases.py
 
  
Los archivos ‘__init__.py’ estarán en blanco. El archivo ‘promedios.py’ tendrá la siguiente estructura:
+
::2. A un símbol d'un procés poden arribar varies línies.
  
from utiles.clases import Estudiante # Se importa la clase 'Estudiante'
+
::3. A un símbol de decisió poden arribar varies línies, però només poden sortir dos (Sí o No, Cert o Fals).
from utiles.funciones import proms # Se importa la función 'proms'
 
N = int(input("Ingrese la cantidad de estudiantes\n"))
 
grupo = [ Estudiante() for x in range(0,N) ]
 
promed = 0.0
 
promia = 0.0
 
for i in grupo:
 
  i.nombre = input("Ingrese el nombre del estudiante (min. 1 caracter)\n")
 
  i.edad = int(input("Ingrese la edad de %s\n" % i.nombre))
 
  i.indice = float(input("Ingrese el I.A de %s (entre 1 y 10)\n" % i.nombre))
 
PROMEDIOS = proms(grupo, N)
 
print("El promedio de las edades es: %s" % PROMEDIOS[0])
 
print("El promedio de los I.A. es: %s" % PROMEDIOS[1])
 
  
El archivo ‘clases.py’ será de la siguiente forma:
+
::4. A un símbol d'inici no poden arribar línies.
  
class Estudiante():
+
::5. D'un símbol fi no surt cap línia.
  nombre  = ""
 
  edad  = 0
 
  indice  = 0.0
 
  
El archivo ‘funciones.py’ será de la siguiente forma:
+
::6. Es poden utilitzar colors per millorar la claredat del diagrama.
  
def proms(A, q):
+
:* Exemple:
  '''  Función:
 
    Calcula los promedios de las edades e indices 
 
    academicos y los almacena en un arreglo.
 
  '''
 
  pred = sum(i.edad for i in A)/q
 
  pria = sum(i.indice for i in A)/q
 
  S = [pred, pria]
 
  return S
 
  
Ahora tienes el poder de estructurar tus proyectos de forma mucho mas ordenada y de hacer importaciones de funciones y objetos que tengas en otros archivos!!
+
[[Imatge:m3_uf2_diagrama_flux_exemple.png |400px|left| Exemple diagrama flux ]]

Revisió de 15:35, 14 set 2023

Descomposició funcional

  • L’objectiu serà resoldre el problema general com a una suma de subproblemes més petits.
  • La solució a cada subproblema s’anomena subrutina o subprograma, i a Java, mètode.
  • Permet la reutilització del codi, facilita la seva lectura i el seu manteniment.
  • Escriure codi més genèric facilita la seva reutilització.

Disseny descendent

  • El mètode del disseny descendent consisteix en descompondre el problema a resoldre en altres més senzills. A aquests se'ls aplica el mateix procediment fins arribar a problemes prou petits que podem resoldre directament.
  • Refinament de l’algorisme (stepwise refinement) és com es coneix aquest procediment de descomposició.
  • Representació en forma d'arbre:
- Cada node és un mòdul, o problema, o solució hipotètica.
- Cada subarbre depenent d'aquest node es fa servir per a la resolució d'aquest subproblema.
- El node del nivell més alt és el problema de partida.
- L’algorisme serà correcte si la solució que es dóna a cada nivell ho és.
- El programa es pot construir de sota a dalt creant primer procediments que resolguin els mòduls de detall que, un cop comprovats seran utilitzats per altres procediments més generals fins a arribar a la creació del programa.
Disseny modular

Reutilització de subproblemes resolts

  • La descomposició mitjançant disseny descendent permet reaprofitar la solució de subproblemes idèntics, o força semblants.
  • Qualsevol subproblema d’un nivell donat pot ser part de qualsevol subproblema d’un nivell superior. Per remarcar
Disseny modular
  • En descompondre un problema, s'ha d'intentar fer-ho de manera que es forci l’aparició de subproblemes repetits, i així la seva resolució es pot reaprofitar en diversos llocs.

Aplicació correcta del disseny descendent

Diferents persones poden arribar a conclusions diferents sobre com dur a terme la descomposició. Entre totes les solucions diferents possibles, algunes es poden considerar millors que d’altres. De fet, res impedeix, partir d'una solució concreta i aplicar refinaments que la millorin.

Criteris per a l'avaluació de la descomposició:

  • Si un problema que sembla a priori força complex es descompon en molts pocs nivells, potser val la pena fer una segona ullada. Inversament, si un problema no massa complex té massa nivells, potser s’ha anat massa lluny en la descomposició.
  • Veure si el nombre de passes incloses a cadascun dels subproblemes no és excessivament gran i és fàcil de seguir i entendre. En cas contrari, potser encara faria falta aplicar nous nivells de descomposició.
  • Repassar que els noms assignats als subproblemes siguin autoexplicatius i expressin clarament la tasca que estan resolent. Sense ni tan sols llegir les seves passes, caldria entendre perfectament què s’assoleix en resoldre’ls. En cas contrari, potser la descomposició no està agrupant conjunts de passes realment relacionades entre elles.
  • Si absolutament cap dels subproblemes és reutilitzat enlloc, especialment en descomposicions en molts nivells, és molt possible que no s’hagi triat correctament la manera de descompondre alguns subproblemes.
  • Vinculat al punt anterior, l’aparició de subproblemes molt semblants o idèntics, però tractats per separat en diferents llocs, també sol ser indici que no s’està aplicant la capacitat de reutilitzar subproblemes correctament.

Programació modular

La programació modular consisteix en dividir un programa gran i/o complex en subprogrames més petits o simples, aconseguint fer-lo més comprensible i manejable. Per això, s'implementen funcions, classes i mòduls.

Funció

Funcions

  • Bloc de codi amb un nom associat.
  • Pot rebre zero o més arguments com a entrada.
  • Por retornar un valor i/o realitzar una tasca.
  • L'ús de funcions permet fer una programació estructurada:
  • modularització: segmentar un programa complex en mòduls més simples facilitant la programació i la depuració.
  • reutilització: una mateixa funció es pot utilitzar des de diferents punts d'un programa i també des de diferents programes.
  • Python disposa de moltes funcions integrades i permet la creació de funcions per part dels programadors.
  • Sintaxi:
def nomFuncio(arg_1, arg_2, ..., arg_n):
    ...
    return value
  • Els arguments es passen per valor: si canvien el seu valor dins de la funció, no canvien "a fora".
  • Per modificar variable no locals a la funció, cal definir-les com a globals en la primera línia.
def nomFuncio(arg_1, arg_2, ..., arg_n):
    global var_1, var_2
    ...
    return value
Exemple senzill:
>>> def salutacio(nom):
...     print("Hola "+ nom + "!")
...
>>> salutacio("Pep")
Hola Pep!


Example function

def saludo(primer_nombre,apellido):
    print(f"Hola, {primer_nombre} {apellido}")
    

saludo("Timmy","Jones",34)

un altre

def saludo(primer_nombre,apellido):
    print(f"Hola, {primer_nombre} {apellido}")
    

saludo("Timmy","Jones")

un altre més

def myFun(arg1, *argv):
	print("First argument :", arg1)
	for arg in argv:
		print("Next argument through *argv :", arg)


myFun('Hello', 'Welcome', 'to', 'M03')


Ejemplo de llamada a una función, con return de varios parámetros y recogida en diferentes variables.

def aHsMinSeg (x):
    '''''Dada una duración en segundos sin fracciones (la función debe 
    invocarse con números enteros) se la convierte a horas, minutos y segundos'''''
    hs = x / 3600
    min = (x % 3600) / 60
    seg = (x % 3600 ) % 60
    return (hs, min, seg)
    '''''Llamada a función'''''
(h, m, s) = aHsMinSeg(3661)
print ("Resultado: ",h,"horas",m,"minutos",s,"segundos")

[funcions amb número indeterminat de paràmetres]

Mòduls

Moduls

__init__

  • Un mòdul és un arxiu amb un codi independent i una determinada funcionalitat.
  • Pot ser utilitzat per qualsevol aplicació.
  • Es poden utilitzar mòduls propis de python, de tercers o propis.
  • Conté funcions, classes, definicions, ...
  • Per poder utilitzar un mòdul s'ha d'importar prèviament.
import modul    # 'modul': nom del mòdul a importar
  • Si volem importar només algunes parts del mòdul:
from modul import funcio_1, funcio_2   # 'funcio_x': funcions del mòdul.

Diagrames de flux

Els diagrames de flux es poden utilitzar per representar gràficament una seqüència ordenada de passos lògics per fer una tasca. Per fer aquesta representació, s'utilitzen un conjunt de símbols en els que es descriuen els passos a fer.

Abans de fer un diagrama de flux es convenient fer un algoritme que descrigui quins són els passos a seguir per fer la tasca.

  • Algoritme: Passos ordenats per fer una tasca.
  • Diagrama de Flux: Representació gràfica amb símbols de l'algoritme.

Un cop tenim l'algoritme / diagrama de flux, haurem de fer el programa utilitzen les ordres corresponents del llenguatge de programació emprat.

  • Símbols emprats:
Símbols diagrama flux
  • Regles:
1. Tots els símbols han d'estar connectats.
2. A un símbol d'un procés poden arribar varies línies.
3. A un símbol de decisió poden arribar varies línies, però només poden sortir dos (Sí o No, Cert o Fals).
4. A un símbol d'inici no poden arribar línies.
5. D'un símbol fi no surt cap línia.
6. Es poden utilitzar colors per millorar la claredat del diagrama.
  • Exemple:
Exemple diagrama flux