Post Destacado

Configurando la Impresión Perfecta de un Libro de Excel

Aunque vivimos en una era digital, a veces todavía es necesario imprimir datos, tablas, gráficos, o información de cualquier tipo que hayamos procesado en Excel. Especialmente si estamos hablando de informes financieros, gráficos estadísticos, o simplemente porque preferiremos analizar la información en formato físico. Sin embargo, Excel es muy flexible y las hojas pueden volverse rápidamente muy extensas, lo que puede complicar las tareas de impresión. A continuación, detallaremos el proceso para configurar y preparar tu libro de Excel para imprimirlo de la mejor manera posible en cada caso. Paso 1: Revisión Preliminar Antes de imprimir, debes revisar cómo quedará el documento una vez impreso. Excel ofrece dos opciones para ello: a. Ve a la pestaña "Archivo", luego elige "Imprimir". Aquí puedes ver cómo se verá tu documento antes de imprimirlo. b.    Utiliza la opción 'Diseño de Página'. Esta perspectiva te dará una vista preliminar de cómo se verá tu libro

Funciones con Argumentos Predeterminados en Python


Las funciones son lógicas y fragmentos de código que pueden ejecutarse (o invocarse) repetidamente en distintos puntos de un programa, evitando la reiteración de código y dotando de mayor (valga la redundancia) funcionalidad al mismo. Su funcionamiento se basa en una serie de entradas, a las que llamamos argumentos, las cuales atraviesan un proceso (la ejecución del código de la función en sí), para finalmente arrojar un resultado (la salida de la función). 

Además de permitirnos ahorrar escritura de código, gracias a estos argumentos, las funciones van más allá de un "copiar-pegar" y pueden producir distintas salidas en función de los valores que les proporcionemos. La expectativa, es que siempre una misma función con los mismos parámetros de entrada, sea capaz de producir la misma salida, dado que conocemos los pasos o código que se va ejecutando en su interior, haciéndola reproducible.

Estos valores otorgados dependerán del contexto en el cual se esté ejecutando la función, y si buen pueden estar "redactados" en el mismo código, lo más frecuente es que sean variables, que hayan capturado información de diferentes medios durante la ejecución del programa.

Lo que nos interesa ver hoy es qué ocurre en los casos que por cualquier motivo, la información que está esperando un argumento de la función no está disponible, ya sea porque no fue capturada o no haya sido explícitamente definida por el programador o usuario.

Partamos de un caso básico que nos resulte familiar, como por ejemplo la siguiente función:

def suma(num1, num2):

    resultado = num1 + num2

    return resultado

La función anterior toma dos argumentos (num1 y num2), los procesa en su interior para calcular la suma de ambos (en este caso, un proceso muy sencillo, pero dentro de una función pueden ocurrir procedimientos de distinta complejidad para llegar al resultado final), y devuelve un resultado, que posteriormente podremos imprimir o almacenar en una variable para su uso, por ejemplo, en otra función.

mi_resultado = suma(5,2)

print(f'El resultado de la suma es: {mi_resultado}')

En el caso anterior, para llegar a nuestro resultado, hemos proporcionado los dos argumentos que requiere la función suma() desde el momento que la hemos definido, es decir, dos valores (los ya mencionados num1, y num2). Una función también podría recibir una cantidad de argumentos distinta, o incluso una cantidad indeterminada de argumentos, pero lo siguiente es extrapolable a todos los casos:

¿Qué ocurriría, si por ejemplo, no contamos con ambos valores al momento de ejecutar una función que ha sido definida con un cierto número de argumentos? Retomando nuestra función anterior, sería el caso por ejemplo de:

suma(5)

La ejecución devolvería un error, que se vería más o menos como:

TypeError: suma() missing 1 required positional argument: 'num2'

y que nos indica que nos hemos olvidado un argumento posicional: num2. Argumento posicional indica que cada uno de los valores que le hemos pasado a la función se incorporará a la misma de acuerdo al orden o posición con la que se los hemos pasado. Para la función suma() es irrelevante, pero por ejemplo para una función resta(), no:

def resta(num1,num2):

    resultado = num1 - num2

    return resultado

Para la función anterior, no es indiferente el orden en el que pasemos los argumentos, ya que por ejemplo resta(5,2) devolverá 3, pero resta(2,5), devolverá -3. Para el caso de suma(), tanto suma(5,2) como suma(2,5) devolverán 7.

El orden no es lo único que determina la información que recibe (o no) una función, y para el caso de las funciones, podemos pasar los argumentos de manera más explícita del siguiente modo:

suma(num1 = 5, num2 = 2)

Con lo cual, el resultado sigue siendo 7, pero hemos hecho algo más explícito el pasaje de la información. Y si, retomando el ejemplo anterior, hiciéramos

suma(num2 = 2)

Es decir, omitiendo otra vez un argumento, pero en esta oportunidad no el segundo (como ocurre de manera predeterminada), sino el primero (explícitamente), el error recibido sería parecido pero diferente:

TypeError: suma() missing 1 required positional argument: 'num1'

En este caso, como habrás previsto, el argumento posicional faltante es num1.

En ciertas ocasiones, por ejemplo porque estemos trabajando con una función compleja que recibe gran cantidad de argumentos, pero que muchos de los cuales suelan ser casi siempre el mismo valor, puede ser algo extenso y agotador tener que declararlos a todos cada vez que se invoca la función.

En su lugar, lo lógico sería preferir tener que declarar únicamente los argumentos que necesitemos cambiar o controlar, y que el resto trabajen con valores predeterminados e iguales en cada oportunidad. Existe una alternativa que nos permite hacer eso, evitando el error "TypeError" que obteníamos en los casos anteriores.

Pensemos una nueva función, por ejemplo, potencia(), la cual reciba también dos argumentos: el primer argumento será la base de la potencia, y el segundo el exponente:

def potencia(base, exponente):

    resultado = base ** exponente

    return resultado

Podríamos plantear que, ante los casos que no se indique un valor en exponente, queremos que nuestra potencia trabaje como un cuadrado (potencia 2). Para permitir este tipo de comportamientos, tendremos que asignarle este valor predeterminado al exponente:

def potencia(base, exponente = 2):

    resultado = base ** exponente

    return resultado

¿Esto quiere decir que exponente siempre valdrá 2 al invocar a la función? Desde luego que no (para ello directamente no crearíamos el argumento), sino que lo que se implica, es que cada vez que se invoque a la función, si no se indica un valor para exponente, al mismo será asignado el valor 2. De esa manera:

print(potencia(2,3))

>> 8

print(potencia(5))

>> 25

Y con lo cual, a pesar de haber brindado únicamente un parámetro a la función potencia(), el resultado queda determinado en lugar de arrojar un error.

El caso

print(potencia(exponente=3))

Aún arrojará un error TypeError, dado que base no tiene valor predeterminado asignado.

Vale la pena prestar especial atención al proceso realizado: para asignar un valor a un argumento posicional, lo asignamos mediante el nombre de dicho argumento y el signo = al invocar la función. Pero para asignar un argumento predeterminado, lo hacemos del mismo modo, pero al definir la función. Esta diferencia es fundamental.

Resulta importante destacar que nuestros argumentos predeterminados no pueden ser seguidos por parámetros sin su valor predeterminado, siguiendo la estructura al definir una función:

  1. Primero, declarar todos los argumentos no predeterminados (argumento)
  2. Luego, los argumentos predeterminados (argumento = valor)
  3. Finalmente, los argumentos indefinidos (*args y **kwargs)

Como comentario final, el objetivo de un argumento predeterminado no es cubrir "olvidos" a la hora de invocar nuestras funciones: en todos los casos tendremos que ser cuidadosos y precisos con el código para poder de esa manera obtener los resultados esperados. Más bien, el objetivo es permitirnos ahorrar tiempo y ganar simplicidad, a la hora de invocar funciones cuando las mismas tienen un número significativo de argumentos, entre los cuales solo unos pocos nos resultan prioritarios.