0% encontró este documento útil (0 votos)
4 vistas

Python Tema2 Parte9 v3

Cargado por

Eduardo Culman
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
4 vistas

Python Tema2 Parte9 v3

Cargado por

Eduardo Culman
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
Está en la página 1/ 18

IBM SkillsBuild | Introducción a Python

Conceptos básicos de
programación
Segmentación de programación modular, recursividad,
global

1
IBM SkillsBuild | Introducción a Python

Índice

Introducción 3

Programación modular 4
Ventajas 4

Interfaz 5

Implementación 5

Tipos de módulos 5

Refinamiento y modularidad 7
El refinamiento sucesivo 7
El concepto de modularidad 7
El diseño descendente o diseño de arriba abajo (Top Down) 7

Ocultación de la información 8

Independencia funcional y calidad del software 8


Cohesión 9
Acoplamiento 1

Estructura del programa y jerarquía de control 2

Diseño de funciones 2
Procedimientos 3
Parámetros 3

Funciones 4
Ámbito de identificador 5

Recursividad 6
Tipos de recursión 6
Etapas del diseño recursivo: 6
Librerías 7
APIs 8

2
IBM SkillsBuild | Introducción a Python

Introducción
• La comprensibilidad, que incluye la legibilidad y
la buena documentación, características que
permiten una mayor facilidad y comodidad en el
A la hora de desarrollar un programa pueden mantenimiento de los programas.
planteársenos preguntas del tipo: ¿sigue nuestro • La eficiencia, que expresa los requerimientos de
programa una programación en módulos? ¿Tiene una memoria y el tiempo de ejecución del programa.
estructura básica o es un caos? ¿Están los
• La flexibilidad o capacidad de adaptación del
procedimientos y funciones bien desarrollados?
programa a variaciones del problema inicial, lo
Nuestro objeto de estudio en este tema será conocer
cual permite la utilización del programa durante
cómo es una programación modular, su estructura
básica y cómo deben ser las funciones y mayor tiempo.
procedimientos de los programas. Se presenta • La “transportabilidad ", que es la posibilidad de
históricamente como una evolución de la usar el mismo programa sobre distintos sistemas
programación estructurada para solucionar sin realizar cambios notables en su estructura.
problemas de programación más grandes y
complejos de lo que ésta puede resolver. Teniendo en cuenta que un programa, a lo largo de su
vida, es escrito solo una vez, pero leído, analizado y
La razón principal para utilizar un ordenador es para modificado muchas más, cobra una gran importancia
resolver problemas (en el sentido más general de la adquirir técnicas de diseño y desarrollo adecuadas,
palabra), o en otras palabras, procesar información como la programación modular que se presenta a
para obtener un resultado a partir de unos datos de continuación, para obtener programas con las
entrada. características mencionadas.

Durante la corta historia de los computadores, el


modo de programar ha sufrido grandes cambios. La
programación era en sus comienzos todo un arte
(esencialmente cuestión de inspiración);
posteriormente diversas investigaciones teóricas han
dado lugar a una serie de principios generales que
permiten conformar el núcleo de conocimientos de
una metodología de la programación. Ésta consiste
en obtener “programas de calidad". Esto se puede
valorar a través de diferentes características que se
exponen a continuación, no necesariamente en orden
de importancia:

• La corrección del programa que, obviamente, es


el criterio indispensable, en el sentido de que se
desean obtener programas correctos que
resuelvan el(los) problema(s) para los que están
diseñados.

3
IBM SkillsBuild | Introducción a Python

Programación modular
Un módulo actúa como una caja negra con la cual el
resto del programa interactúa a través de una
sección de interfaz. La interfaz (o vista pública) es
una colección de declaraciones de constantes, tipos,
La programación modular es la técnica de
variables, procedimientos, funciones, etc. La otra
programación basada en la filosofía del diseño
sección principal de un módulo es la implementación
descendente, que consiste en dividir el problema
(o vista privada) que incluye el código de los
original en diversos subproblemas (y estos a su vez
procedimientos y demás elementos constitutivos de
en otros más pequeños, obteniendo una estructura
la parte ejecutable del módulo.
jerárquica o en árbol) que se pueden resolver por
separado, para después recomponer los resultados y Para efectuar un buen diseño modular los algoritmos
obtener la solución al problema. Un subproblema se que se van a desarrollar se han de concebir como una
denomina módulo y es una parte del problema que jerarquía de módulos intercomunicados donde cada
se puede resolver de manera independiente. uno de ellos presenta una función clara y
diferenciada y en la que ningún módulo accede
directamente al interior de otros módulos sino que
siempre utiliza los mecanismos de interfaz.

Ventajas
• Facilita el diseño descendente
• Disminuye la complejidad del algoritmo
• Disminuye el tamaño total del programa
• Reusabilidad: ahorro de tiempo de programación
• División de la programación entre un equipo de
programadores reducción del tiempo de

Un módulo es una colección estática de desarrollo

declaraciones definidas en un ámbito de visibilidad • Facilidad en la depuración: comprobación


particular y oculto al resto del programa con el que se individual de los módulos
comunica por una sección de interfaz donde se • Programas más fáciles de modificar
incluyen la lista de exportaciones. Usando módulos • Estructuración en librerías específicas (biblioteca
se construyen las unidades en que se ha de de módulos)
descomponer cualquier programa mínimamente
importante. Los módulos se conectan entre sí dando
lugar a una estructura modular en árbol que permite
resolver el problema de programación planteado.

4
IBM SkillsBuild | Introducción a Python

Interfaz
Para servirse de un tipo o procedimiento ajeno a un
módulo es obligatorio especificar el lugar donde se
han definido originalmente dichos elementos.
Además, es conveniente que esa declaración de
Un módulo puede ofrecer a la "comunidad" de
objetos ajenos al módulo pero usados en él, se lleve a
módulos sus propios recursos, tipos y
cabo en una sección bien diferenciada. Para tal fin se
procedimientos dentro de lo que se conoce como
puede utilizar alguna versión de la denominada lista
sección de interfaz del módulo. Normalmente es
de importaciones.
posible exportar cinco tipos de elementos:
constantes, tipos, variables, procedimientos y Cada lenguaje presenta sus peculiaridades, así, en C,
funciones. las importaciones se pueden incluir explícitamente
declarando los procedimientos y funciones en el
La importación y la exportación constituyen acciones
mismo módulo o haciendo uso de un archivo de
simétricas. Para que un módulo pueda importar un
cabeceras con la sintaxis: # include
tipo, procedimiento u otro elemento es preciso que
"archivoDeExportaciones.h" donde
otro lo exporte. Por supuesto, es posible que el
archivoDeExportaciones corresponde al nombre del
mismo módulo se comporte como exportador e
archivo concreto que se utilice.
importador.

Tipos de módulos

Según su función dentro del programa:

• Programa o módulo principal.

Implementación • Módulos o módulos secundarios.

Según su uso:

En la parte de implementación se detallan las • Funciones: devuelven un valor (evaluación de la


definiciones y el diseño de todos los elementos que función).
el módulo contiene. La implementación puede incluir, • Procedimientos: realizan tareas, pero no
asimismo, la lista de importaciones correspondiente devuelven ningún valor directamente.
a los elementos exteriores utilizados por el módulo.
Según los mecanismos de activación:
Como hemos visto, cuando se lleva a cabo un diseño
• Invocados por referencia.
por descomposición modular, suele ocurrir que
• Invocados mediante interrupción (en entornos de
algunos módulos hacen referencia a la interfaz de
tiempo real).
otros. Ello puede suceder cuando un módulo usa un
tipo declarado en otro sitio o llama a un
procedimiento o función que se han definido fuera
del propio módulo.

5
IBM SkillsBuild | Introducción a Python

Según el camino de control (describe la forma en la


que se ejecuta internamente):

• Módulos convencionales: tienen una única


entrada y una única salida y ejecutan
secuencialmente una tarea en cada momento.
• Módulos reentrantes: diseña de forma que de
ninguna manera pueda modificarse a sí mismo o
a las direcciones que referencia localmente. Así,
el módulo puede ser usado para más de una
tarea concurrentemente.

Dentro de una estructura de programa:

• Un módulo secuencial que se referencia y se


ejecuta sin interrupción aparente por parte del
software de la aplicación.
• Un módulo incremental que puede ser
interrumpido, antes de que termine, por el
software de la aplicación y, posteriormente,
restablecida su ejecución en el punto en que se
interrumpió. Este tipo de módulo se suele
denominar corrutina.
• Un módulo paralelo que se ejecuta a la vez que
otro módulo, en entornos de multiprocesadores
concurrentes. Una denominación utilizada para
este tipo es conrrutina.

6
IBM SkillsBuild | Introducción a Python

Refinamiento y
Para un caso general, este resultado es
intuitivamente obvio. Se tarda más tiempo en

modularidad resolver un problema difícil.

Se ha encontrado otra propiedad interesante, a partir


de la experimentación sobre la resolución humana de
El refinamiento sucesivo problemas, es la siguiente C(pl+p2) > C(p1) + C(p2)
Propuesto por Niklaus Wirth en 1971, fue una de las que indica que la complejidad de un problema

primeras estrategias de diseño descendente. En ella, compuesto por p1 y p2 es mayor que la complejidad
la arquitectura de un programa se desarrolla en total cuando se considera cada problema por
niveles sucesivos de refinamiento de los detalles separado. Se puede deducir que
procedimentales. Se desarrolla una jerarquía E(pl+p2) > E(p1) + E(p2)
descomponiendo una declaración macroscópica de
Esto indica que es más fácil resolver un problema
una función de forma sucesiva, hasta que se llega a
complejo cuando se divide en trozos más
las sentencias del lenguaje de programación.
manejables. De la desigualdad anterior se podría

El refinamiento es, realmente, un proceso de concluir que, si partiéramos el software

elaboración. Se comienza con una declaración de la indefinidamente, el esfuerzo requerido para

función (o una descripción de la información). Es desarrollarlo sería insignificantemente pequeño. Sin

decir, la declaración describe la función o la embargo conforme crece el número de módulos, el

información conceptualmente, pero no proporciona esfuerzo (coste) asociado a los interfaces entre los

información sobre el funcionamiento interno de la módulos también crece. Por lo tanto, debe evitarse

función o sobre la estructura interna de la tanto la modularización excesiva como que ésta

información. El refinamiento hace que el diseñador quede pobre.

amplíe la declaración original, dando cada vez más


detalles conforme se producen los sucesivos El diseño descendente o diseño de
refinamientos (elaboraciones).
arriba abajo (Top Down)
Utiliza los conceptos de refinamiento y modularidad
El concepto de modularidad
descritos anteriormente. Consiste en una serie de
Se refiere al hecho de que el software se divida en descomposiciones sucesivas del problema inicial,
componentes con nombres y ubicaciones que describen el refinamiento progresivo del
determinados, que se denominan "módulos" y que se conjunto de instrucciones que van a formar parte del
integran para satisfacer los requisitos del problema. diseño.

Para ilustrar este punto, consideremos la siguiente La utilización de esta técnica de diseño tiene los
disquisición, basada en observaciones sobre la siguientes objetivos básicos
resolución humana de problemas.
• Simplificación del problema y de los bloques
• Sea C(x) una función que define la resultantes de cada descomposición.
complejidad de un problema x y E(x) una
• Las diferentes partes del problema pueden
función que define el esfuerzo (en tiempo)
ser diseñadas/desarrolladas de modo
requerido para resolver un problema x. Para
independiente e incluso por diferentes
dos problemas, p1 y p2, si C(p1) > C(p2) se
personas.
deduce que E(p1) > E(p2)

7
IBM SkillsBuild | Introducción a Python

• El diseño final queda estructurado en forma El uso del ocultamiento de información como criterio
de bloques o módulos, lo que hace más de diseño para los sistemas modulares, revela sus
sencilla su implementación y posterior mayores beneficios cuando se hace necesario
mantenimiento. realizar modificaciones, durante la prueba y, más
La principal ventaja del diseño Top Down es que adelante, el mantenimiento del software. Debido a
aminora la dificultad de resolución y posterior que la mayoría de los datos y de los procedimientos
mantenimiento de los problemas de diseño. Como estarán ocultos a otras partes del software, será
desventaja asociada tenemos que, a medida que se menos probable que los errores introducidos
divide el problema en subproblemas y el número de inadvertidamente durante la modificación se
módulos crece, se produce un incremento de los propaguen a otros lugares del software.
interfaces entre estos con la consiguiente
complejidad asociada.
Independencia funcional y
Ocultación de la calidad del software
información
El concepto de independencia funcional es una
derivación directa del de modularidad y de los
El principio de ocultamiento de información conceptos de abstracción y ocultamiento de
Propuesto por Parnas sugiere que los módulos se han información.
de "caracterizar por decisiones de diseño que los
La independencia funcional se adquiere
oculten unos a otros". En otras palabras, los módulos
desarrollando módulos con "una clara" función y una
deben especificarse y diseñarse de forma que la
"aversión" a una excesiva interacción con otros
información (procedimientos y datos) contenida
módulos. Dicho de otra forma, se trata de diseñar
dentro de un módulo sea inaccesible a otros módulos
software de forma que cada módulo se centre en una
que no necesiten tal información.
subfunción específica de los requisitos y tenga una
El ocultamiento implica que para conseguir una interfaz sencilla, cuando se ve desde otras partes de
modularidad efectiva hay que definir un conjunto de la estructura del software.
módulos independientes, que se comuniquen con los
Es importante la independencia funcional en el
otros solo mediante la información que sea necesaria
desarrollo de aplicaciones informáticas porque el
para realizar la función del software. La abstracción
software con modularidad efectiva, es decir, con
ayuda a definir las entidades procedimentales (o de
módulos independientes, es fácil de desarrollar
información) que componen el software. El
porque su función puede ser partida y se simplifican
ocultamiento establece y refuerza las restricciones
los interfaces (considérense las implicaciones
de acceso a los detalles procedimentales internos de
cuando el desarrollo es realizado por un equipo). Los
un módulo y a cualquier estructura de datos
módulos independientes son más fáciles de
localmente utilizada en el módulo.
mantener (y de probar) debido a que se limitan los
efectos secundarios producidos por las
modificaciones en el diseño/código, se reduce la
propagación de errores y se fomenta la reutilización
de los módulos. Resumiendo, la independencia
funcional es la clave de un buen diseño y el diseño es
la clave de la calidad del software.
8
IBM SkillsBuild | Introducción a Python

La independencia se mide con dos criterios


cualitativos: la cohesión y el acoplamiento. La
cohesión es una medida de la fortaleza funcional
relativa de un módulo. El acoplamiento es una
medida de la interdependencia relativa entre los
módulos.

Cohesión
Mide el grado de conexión funcional entre los
elementos (instrucciones, definición de datos,
llamadas a módulos) de un mismo módulo. Cuanto
más fuerte sea la cohesión mejor será el
mantenimiento del módulo.

9
IBM SkillsBuild | Introducción a Python

Acoplamiento
Es el grado de interdependencia entre los módulos de
un sistema. Este criterio debe minimizarse, con ello se
logra atenuar el ruido del sistema (los errores de un
módulo no se propagan a otros) y se realiza el
mantenimiento sin mirar en el interior de otros
módulos.

1
IBM SkillsBuild | Introducción a Python

Estructura del programa y


• La visibilidad (scope) indica el conjunto de
componentes del programa a los que un módulo

jerarquía de control dado puede invocar o utilizar sus datos, incluso


cuando lo haga indirectamente. Se trata pues de
un concepto relacionado en parte con la
La jerarquía de control, también denominada
ocultación de la información. Así, un dato es
estructura del programa representa la organización
visible por un módulo dado cuando desde éste se
(frecuentemente jerárquica) de los componentes del
programa (módulos) e implica una jerarquía de puede usar o variar su valor y, un módulo es
control. No representa pues, aspectos visible desde otro, cuando este último puede
procedimentales del software, tales como la invocar la ejecución de aquél.
secuencia de procesos, la ocurrencia u orden de • La conectividad indica el conjunto de
decisiones o la repetición de operaciones. componentes a los que directamente se invoca o

Para representar la jerarquía de control se utilizan de los que se utilizan sus datos en un
muchas notaciones diferentes. La más común es un determinado módulo. Por ejemplo, un módulo
diagrama en forma de árbol denominado diagrama de que en un momento dado provoca la ejecución
estructura. de otro módulo, está conectado a ese último.

Podemos concluir diciendo que la visibilidad es pues


una medida de la conectividad potencial de un
programa y que, cuanto mayores sean estas
magnitudes menor es el nivel de ocultamiento de la
información y por tanto más elevadas las
posibilidades de que aparezcan los molestos efectos
laterales.

Diseño de funciones
• El grado de salida (fan out) es una medida del
número de módulos que están directamente Uno de los componentes que los lenguajes
controlados por otros módulos. estructurados incorporan son un tipo de secuencias
• El grado de entrada (fan in) indica cuántos algorítmicas individualizadas que pueden recibir o no
módulos controlan directamente a un módulo valores de entrada y que también pueden devolver o
dado. no valores de salida.
• Las relaciones de control entre los módulos se
expresan de la siguiente forma: un módulo que Se trataría de sustituir todo un conjunto de
controla a otro módulo se dice que es superior a instrucciones que puede incluir cualquier
él, e inversamente, un módulo controlado por combinación de las denominadas estructuras básicas
otro se dice que es un subordinado del (secuencial, condicional, iterativa) por un
controlador. identificador que puede incorporar la declaración de
• La jerarquía de control también representa dos valores. Posteriormente, en cualquier lugar del
características, sutilmente diferentes, de la programa se podrá invocar al conjunto de
arquitectura del software: la visibilidad y la instrucciones nominado utilizando el identificador.
conectividad.

2
IBM SkillsBuild | Introducción a Python

Tras la ejecución, y según el tipo de estructura Parámetros


utilizada, se pueden obtener resultados devueltos.
Los parámetros son tanto las variables usadas en la
definición del procedimiento como los valores
Procedimientos utilizados en la llamada. A los primeros se los

Sirven para definir partes de un programa mediante denomina parámetros formales y a los segundos

la asociación de un identificador. Posteriormente parámetros reales. Los parámetros reales, según los

dichas partes se pueden activar utilizando sentencias casos, pueden ser constantes, variables definidas en

de llamada. Un procedimiento es pues un algoritmo el ámbito del procedimiento llamante o expresiones

diseñado de tal modo que es susceptible de ser (mezcla de constantes, variables y operadores).

llamado por otros algoritmos que, a su vez, pueden


ser procedimientos.

La llamada a un procedimiento se realiza escribiendo


su nombre seguido de las expresiones sobre las que
deseemos que trabaje. Estas van encerradas entre
paréntesis y en el orden en que han sido
especificadas en el procedimiento llamada.

La lista de parámetros formales {pf1, pf2,..., pfn} y la


de parámetros reales de cualquier llamada al mismo
{pr1, pr2,..., prm} deben cumplir las siguientes
condiciones:

• m=n
• Dados una pareja de parámetros que ocupan la
misma posición en sus respectivas listas pfi y pri
su tipo debe ser igual o, al menos, compatible.
Sin embargo, su nombre no tiene por qué ser
igual.

En función de su papel en el procedimiento, los


parámetros, formales o reales, pueden ser de tres
clases:

• Parámetros de entrada: son aquellos que se


utilizan para aportar datos al procedimiento. Si
dentro de éste se produce un cambio en el valor
del parámetro formal el parámetro real no se
verá afectado. Los parámetros reales en este
caso pueden ser constantes, variables o
expresiones.

3
IBM SkillsBuild | Introducción a Python

• Parámetros de salida: son aquellos que se En general, todos los lenguajes suelen dividir esta
utilizan para exportar datos desde el definición en dos partes:
procedimiento. No aportan valor inicial por lo que
• Cabecera o interfaz: incluye el identificador del
son directamente inicializados por el
procedimiento usualmente precedido de una
procedimiento que les asigna valores. Así, los
palabra reservada tal que procedure, y la lista de
cambios producidos en el valor del parámetro
parámetros formales con cero o más parámetros.
formal afectarán al parámetro real que deberá
En esta lista se indica el tipo de los parámetros y
ser una variable.
su clase. Para la clase se debe emplear alguna
• Parámetros de entrada/salida: son aquellos
notación específica. Nosotros, a efectos de
cuya función incluye a las dos anteriores. Por un
explicación, utilizaremos las siguientes palabras
lado aportan valores y por otro son modificados
reservadas que precederán a los parámetros:
por el procedimiento para exportar valores. Los
o De entrada, van precedidos por la
parámetros reales tienen también que ser
palabra reservada ent.
variables.
o De salida, por la palabra sal.
o De entrada/salida, por la palabra
Paso de Parámetros entSal.
• Por valor: únicamente nos interesa el valor, no • Cuerpo: el cuerpo del procedimiento los
las modificaciones que pueda tener dentro del componen las declaraciones e instrucciones en
subalgoritmo. Se trabaja con una copia del valor las que se ejecuta el algoritmo propio del
pasado. Son parámetros unidireccionales, que procedimiento.
pasan información desde al algoritmo al
subalgoritmo. Puede ser cualquier expresión Funciones
evaluable en ese momento.
• Por referencia: se pasa una referencia a la
Son procedimientos con características peculiares: a
posición de memoria donde se encuentra dicho.
excepción de un parámetro de salida, todos los
Se utilizan tanto para recibir como para transmitir demás son de entrada. El parámetro de salida sirve
información entre el algoritmo y el subalgoritmo. para albergar el valor devuelto por la función.
Debe ser obligatoriamente una variable.
No es casual que las funciones tengan un único
parámetro de salida. De hecho, las funciones de
Definición de procedimientos salida tienen sentido como clase de subprograma
Se utilizará la sintaxis propia del lenguaje de diferente a los procedimientos en que calculan un
programación que se esté utilizando. valor, valor que se asigna al parámetro de salida y al
que desde fuera de la función se accede usando el
identificador de la propia función empleado en la
llamada. Es por ello que en la llamada a una función
el parámetro de salida no debe aparecer en la lista de
parámetros. Esta estructura, además de facilitar la
escritura de las aplicaciones, evita efectos laterales
indeseados que se pueden producir cuando se usan
parámetros de e/s típicos de los procedimientos.

4
IBM SkillsBuild | Introducción a Python

La instrucción de llamada evalúa la función y realiza Ámbito de identificador


una asignación interna al identificador que luego
puede ser asignado, en la misma llamada, a una Conjunto de sentencias donde puede utilizarse ese
variable. Las llamadas a funciones pueden también identificador.
aparecer en expresiones complejas diferentes a la
• Variables locales: variable declarada dentro de
asignación. El requisito que se debe siempre cumplir
un subprograma y, por tanto, solo disponible
es que el tipo del valor que la función retorna sea
durante el funcionamiento del mismo.
compatible con el requerido en la expresión. A este
tipo del valor devuelto se le conoce como tipo de la • Variables globales: variables declaradas en el
función. programa principal y, por ello, pueden ser
utilizadas por el programa principal y por todos
La definición de funciones es muy parecida a la de los
sus subprogramas.
procedimientos. No obstante, existen una serie de
• Efecto Lateral: efecto de un módulo sobre otro
diferencias:
módulo que no es parte de la interfaz definida
explícitamente entre ellos.

Reglas para el cálculo del ámbito de un


identificador:

• Un identificador declarado en un bloque es


accesible únicamente desde ese bloque y todos
los bloques incluidos en él (se considera local a
ese bloque). Un parámetro formal se considera
también una declaración local al bloque de la
función.
• Los identificadores declarados fuera de cualquier
bloque se consideran globales y pueden ser
• Como hemos dicho, la función tiene un tipo igual
utilizados desde cualquier punto del fichero.
al del valor que devuelve. Para especificar este
tipo, en la definición de la función, lo añadiremos • Cuando tenemos un bloque dentro de otro

al final de la cabecera, tras la lista de parámetros bloque y en ambos se declaran identificadores


y utilizando la sintaxis normal de especificación con el mismo nombre, el del bloque interno
de tipos, es decir, dos puntos, ':', seguidos del "oculta" al del bloque externo.
tipo devuelto.
• Al ser todos los parámetros de entrada, en la lista
de parámetros formales no se utiliza la etiqueta
ent.
• El valor devuelto por la función se indica usando
la palabra reservada retorna seguida por la
expresión correspondiente a dicho valor. Es usual
adoptar el convenio de que esta instrucción
aparezca únicamente al final de la función y que
sea la única forma de terminar la función.

5
IBM SkillsBuild | Introducción a Python

Recursividad
• NO FINAL: El resultado obtenido de la llamada
recursiva se combina para dar lugar al resultado
de la función que realiza la llamada.
• Un objeto es recursivo si su definición requiere la
definición previa del objeto en un caso más
sencillo.
• Una función es recursiva si su resolución requiere
la solución previa de la función para casos más
sencillos.
Recursión múltiple:
• Un algoritmo A que resuelve un problema P es
recursivo si está basado directa o Si alguna llamada puede generar más de una llamada
indirectamente en sí mismo. adicional.

Los algoritmos recursivos son especialmente


apropiados si el propio problema o el propio cálculo a
realizar o la propia estructura con la que trabaja el
problema aceptan una definición recursiva. Sin
embargo, la existencia de tales definiciones no
garantiza que la mejor forma de resolver un problema Recursión anidada:
pase por utilizar un algoritmo recursivo. Hay recursión anidada cuando uno de los argumentos
de la función recursiva es el resultado de la llamada
Siempre que diseñemos un algoritmo recursivo habrá
recursiva.
que asegurarse no solo de que el número de
llamadas es finito (la recursión acaba) sino también
de que es pequeño, ya que hace falta espacio de
memoria (pila de recursión) para almacenar en cada
llamada los objetos locales, los parámetros de la
llamada y el estado del proceso en curso para
recuperarlo cuando acabe la llamada actual y haya
que reanudar la antigua. Etapas del diseño recursivo:
Un diseño recursivo constará de las siguientes
Tipos de recursión etapas:

Recursión lineal:
• Definición del problema.

Si cada llamada recursiva genera, como mucho otra • Análisis de casos. Identificación de la función
llamada recursiva limitadora.
• Trascripción algorítmica y verificación de cada
• FINAL: si la llamada recursiva es la última
caso.
operación que se efectúa, devolviéndose como
• Validación de la inducción: la función limitadora
resultado lo que se haya obtenido de la llamada
decrece estrictamente en las llamadas.
recursiva sin modificación alguna.

6
IBM SkillsBuild | Introducción a Python

Existe recursividad en algoritmos cuando un • Adaptable: todos los aspectos específicos de la


algoritmo se invoca a sí mismo o es invocado en otro plataforma deben estar claramente identificados
algoritmo previamente llamado. La recursividad y aislados, de manera que puedan realizarse
requiere dos condiciones para su correcto
sustituciones y adaptaciones locales (por
funcionamiento:
ejemplo, mediante el uso de funciones propias
• Las sucesivas invocaciones deben ser que intermedien entre el código de la aplicación y
efectuadas con versiones cada vez más las invocaciones a los procedimientos de
reducidas del problema inicial.
biblioteca).
• Debe existir una condición de fin de las • Eficiente: los componentes deben ser de fácil
llamadas o fin de la recursividad, sin esta
incorporación al código propio (eficiencia en
condición de terminación, el algoritmo no
podría construirse siguiendo esta técnica y su términos de recursos de compilación), utilizar
ejecución produciría un ciclo infinito. cantidades razonables de memoria y tiempo de
La recursividad y la iteración son los dos mecanismos ejecución (eficiencia en ejecución) y de uso
suministrados por los lenguajes de programación comprensible y seguro (eficiencia en términos de
para describir cálculos que han de repetirse un cierto recursos de desarrollo).
número de veces. • Segura: es un requisito fundamental que la
biblioteca esté completamente probada en todos
los entornos previsibles. Uno de los indicadores
Librerías
de esa robustez es el uso de excepciones para
Una biblioteca (librería si traducimos library "por identificar condiciones para las cuales se violan
libre") es un conjunto documentado, probado y, en su
las precondiciones de un algoritmo. Cuando
caso, previamente compilado, de procedimientos y
funciones que es posible invocar desde otro estas excepciones se generen el sistema debe
programa. Las bibliotecas son un claro ejemplo de ser capaz de mantener la estabilidad sin que se
reutilización del software. produzcan reacciones anómalas, rupturas
Una biblioteca básica debe proporcionar una bruscas de la secuencia de ejecución o
colección de estructuras de datos, funciones y corrupciones en el espacio de direcciones del
procedimientos independientes del tipo de aplicación programa.
donde se vayan a usar. Esta colección debe ser
• Simple: característica que es cada vez más difícil
suficiente para cubrir las necesidades de la mayoría
de cumplir (en este sentido ayudan mucho las
de las aplicaciones en los lenguajes que permitan su
técnicas O.O.). Se trata de dotar a la biblioteca de
uso. Además, una biblioteca ideal debe ser:
una organización clara y consistente que facilite
• Completa: la biblioteca debe proporcionar una la identificación y selección de las estructuras y
familia de subprogramas, unidas por un interfaz procedimientos adecuados para el fin requerido.
compartido pero empleando cada representación • Extensible: los desarrolladores propios deben
diferente, de manera que los desarrolladores ser capaces de añadir funcionalidad a la
puedan seleccionar las que sean más apropiadas biblioteca sin alterar su integridad arquitectónica
para la aplicación de que se trate. original.

7
IBM SkillsBuild | Introducción a Python

• Independiente de la plataforma final de Esto se realiza normalmente para programas muy


ejecución: característica que está adquiriendo grandes o simplemente cuando queremos realizar
cada vez una mayor importancia. Se trata de una librería de subprogramas.

hacer la biblioteca lo más independiente que sea • Compilación de un programa en un solo


posible del hardware y sistema operativo donde fichero:
finalmente se ejecute la aplicación que se está
desarrollando. Para ello se crean bibliotecas
abstractas que actúan como interfaz. Estas
• Compilación de un programa en varios
bibliotecas se conectan de forma transparente
ficheros:
para el desarrollador con otras que sí dependen
de los servicios de la plataforma. Dicha conexión
se puede producir, bien al compilar el código, con
lo que habrá que recompilar para cada tipo de
plataforma, bien en tiempo de ejecución de
forma dinámica, como ocurre, por ejemplo, con
las bibliotecas de clases de Java, lo que obliga al
uso de las conocidas como "máquinas virtuales".

APIs Como ya hemos indicado, la mayoría de los lenguajes


permiten al programador la creación de bibliotecas
Una API (Application Programming Interface), en de funciones que pueden ser invocadas desde su
castellano, interfaz para la programación de programa y aparecen como si estuviesen elaboradas
aplicaciones es un conjunto de bibliotecas de dentro del propio lenguaje. Usualmente, en entornos
programación, que elaboran y publican los Windows, los módulos de programas que contienen
fabricantes de elementos tales como sistemas las funciones están precompilados en archivos de
operativos o dispositivos hardware, para permitir a programas objeto (.obj) que pueden agruparse en
los programadores de aplicaciones utilizar los archivos de bibliotecas (.lib) utilizando un
servicios y posibilidades de dichos elementos. Por bibliotecario (un programa auxiliar o parte de un
extensión, se denomina API a cualquier grupo de entorno integrado de desarrollo IDE).
funciones que son parte de ciertas aplicaciones pero
que son utilizables desde otras aplicaciones. Cuando se debe crear una versión final ejecutable de
una aplicación, un enlazador analiza los archivos
Cuando dividimos un problema en distintos módulos, objeto de la aplicación buscando referencias a
no siempre ha de corresponder cada módulo a un funciones que no están definidas en el propio
subprograma. Puede corresponder a todo un programa, luego recorre todos los archivos de
conjunto de subprogramas que estarán agrupados en bibliotecas cuyo uso se ha solicitado, buscando las
un fichero independiente. La principal utilidad de funciones que faltan. El enlazador extrae los módulos
dividir el programa en ficheros distintos es que se que contienen las funciones invocadas, los incluye en
pueden programar y compilar por separado. De esta el archivo ejecutable y los enlaza con las llamadas
manera no hace falta compilar cada vez todo el del programa de aplicación.
programa.

8
IBM SkillsBuild | Introducción a Python

A este proceso se lo conoce como enlace estático, ya


que toda la información de direccionamiento que
necesita el programa para el acceso a las funciones
de biblioteca queda fijada definitivamente cuando se
crea el ejecutable y permanece invariable en tiempo
de ejecución. Tradicionalmente, los enlazadores
incluyen los módulos enteros cuando se los enlaza en
los ejecutables finales, aunque las últimas versiones
de IDE ya son capaces de extraer únicamente el
código correspondiente a la función referida.

El enlace estático produce un gran desperdicio de


memoria dado que cada programa incluye una copia
propia de cada librería utilizada (ej: imaginar el
manejo de ventanas en Windows)

Con el enlace dinámico, los módulos de programas


conteniendo las funciones también son
precompilados en archivos de programas objeto
(.obj), pero, en lugar de agruparlos en archivos de
bibliotecas, son enlazados en un formato especial de
archivo ejecutable de Windows conocido como DLL7,
biblioteca de enlace dinámico. Cuando se construye
una DLL, el constructor especifica qué funciones van
a ser accesibles desde otras aplicaciones en
ejecución mediante la técnica, ya estudiada,
denominada exportación.

Al crear un archivo ejecutable para Windows, el


enlazador analiza los archivos objeto de la aplicación
y elabora una lista de todas aquellas funciones que
no están ya incluidas en el código del programa junto
con la indicación de las bibliotecas de enlace
dinámico donde se encuentran.

Cuando se ejecuta una aplicación con acceso a DLLs,


cada vez que se invoca una función de las ubicadas
en la biblioteca de enlace dinámico, la dirección real
de enlace es calculada y la función se enlaza
dinámicamente con la aplicación. De este modo,
aunque existe una única copia en memoria por cada
DLL, los programas pueden compartir las funciones
incluidas en dicha biblioteca.

También podría gustarte