Aclarando funcións e variables

Nesta páxina non temos exercicios, pero intentamos aclarar cousas importantes coas funcións e as variables que poden levar a erros conceptuais moi habituais:

Seguramente prefiras ir traballando un pouco coas funcións en Python antes de ler esta parte. Podes visitar o resto das páxinas de Python e cando xurdan problemas ou aparezan mensaxes raros ao executar o código coas funcións e as variables voltar.

A importancia de secuenciar: Name ____ is not defined

Cando apareza esa mensaxe de erro estás a utilizar un nome de variable ou función non definido anteriormente. É un erro de secueciación. O máis probable é que apareza se invocas unha función antes de creala:


Código - función invocada antes de tempo

 


Saída

 


Código - variable creada posteriormente

 


Saída

 

No segundo exemplo vemos o importante de secuenciar correctamente. O parámetro ten valor, pero está dado despois de chamar á variable.

Función en busca de parámetro/argumento (required positional argument)

Cando apareza un mensaxe de erro similar a TypeError: proba() missing 1 required positional argument: 'nome' tes que lelo da seguinte maneira: a función, proba(), ten un parámetro, nome, e non lle dimos un valor antes ou no momento de chamar á función. Se unha función ten 3 parámetros e só lle damos 2 pasará o mesmo.


Código - O parámetro ten valor pero fora da función, a función é chamada sen valor para o parámetro

 


Saida

 


Código - chamamos á función e damos un valor ao parámetro

 


Saída

 

Convén pensar con calma por que non funciona o primeiro código. Temos un parámetro, nome, e ademáis unha variable que se chama igual e ten un valor, pero ao chamar á función o facemos sen valor no parámetro, por iso da erro. Isto pode e debe ser confuso, pero é unha das cousas que fai máis sinxelo e amigable a Python. Por exemplo, grazas a isto é moito máis sinxelo reciclar código dun programa a outro.

Se complicas a función simplificarás o programa: Argumentos e retornos

Podemos establecer unha taxonomía de funcións, dende as máis simples pero menos útiles, ás máis complexas e útiles.

1.- Función sen parámetro.

En Python podes crear funcións sen parámetros, e chamalas polo seu nome:


Función sen parámetros

 


Saída

 

Cal é o problema de facelo así?: Que tes que utilizar sempre o mesmo nome das variables, a e b. E non é tan doado copiar a función a outro programa, porque tes que usar as mesmas variables (estes programas de proba son moi sinxelos, falamos de programas de complexidade media).

2.- Función con parámetros.

Se modificamos a función, podemos utilizala con calesquera outras variables, e incluso reciclala noutro programa:


Función con argumentos

 


Saída

 

O normal é rematar a función coa orde return, retorno, pero neste caso funcionaría igual sen ela. Pero é unha boa práctica de programación facelo así, facilita a lectura do código.

3.- Función con parámetros que devolve o resultado nunha variable.

Pero aínda temos un problema: a variable suma garda o resultado da función. Se queremos utilizala fora da función non vai funcionar (ver máis abaixo o problema "Dentro/Fóra"). Ou sexa, como podemos debemos crear unha variable dentro da función para almacenar o resultado de aplicar á función a uns parámetros e utilizar fora da función esa variable?. Pois retornando, return, o resultado da función. así é como podemos utilizalo:


A variable suma almacena o resultado da función; podemos utilizala fora dela.

 


Saída

 

4.- Función con número de parámetros indeterminado: *args

A función anterior podemos aplicala só a a dous parámetros. Pero e se queremos sumar un número calesquera de valores?. Pois sustituimos os parámetros por *args e podemos pasar a función a calquera número de parámetros. O de *args fai referencia a argumentos.


Código - Co bucle percorremos o nº indeterminado de argumentos

 


Saída

 

Se agora quiseras sumar 10 variables en vez de 4 poderías facelo facilmente.

Se queres mellorar o código podes probar a escribir na última liña: print('A suma total de {} + {} + {} + {} é '.format(a,b,c,d), suma_total)

5.- Función que devolve 2 ou  máis resultados.

Por último podemos facer que a función devolva máis dun valor, cada un gardado nunha variable.


Función con 2 resultados

 


Saída

 

O problema "Dentro/Fora": variables globais, locais e nonlocais

O problema das variables globais e locais remata sendo tan sinxelo como a explicación de cando estás Dentro e cando Fóra, e tan importante de entender coma calquera cousa que che teñan explicado en Barrio Sésamo:

Se volvemos por un momento a Scratch podemos lembrar que ao crear unha variable temos dúas opcións, para todas as figuras ou só para unha:

Se a creamos para todas as figuras, logo non podemos crear outra variable co mesmo nome cando creamos unha segunda figura, pero a cambio xa a temos creada esta variable e podemos utilizala no código da nova figura. Se a creamos só para a primeira figura, podemos repetir nome na variable da segunda figura pero non podemos utilizar a primeira variable no código da segunda.

Isto ten unha certa equivalencia en Python, pero é un pouquiño máis lioso. En Scratch o normal é crear variables globais, e poñerlle nomes distintos á de cada figura.

A lembrar

 

En Python usar este tipo de variables globais para todo o programa se considera unha mala práctica de programación, non está aconsellada (agás para definir constantes e outras excepcións) en programas de complexidade media, aínda que o facemos normalmente en programas sinxelos para aprender a programar.

 

En Python3 temos 3 posibilidades para unha variable: global, local e nonlocal. Global sería a creada para todo o programa (similar á de Scratch para todas as figuras) e pode usarse dentro das funcións, local é creada dentro da función (similar á de Scratch para unha figura) e non pode utilizarse fora dela, nonlocal é creada dentro dunha subfunción (unha función aniñada noutra) e o seu valor é dado pola función.

(nota: declarar unha variable é creala, poñerlle nome e darlle un valor inicial que logo pode variar)

O importante non son os nomes, senón saber cales van ser o problemas no código coas variables.

Global vs local

Cando creamos unha variable fora dunha función, iso é unha variable global. Cando a creamos dentro dunha función é local.

Os problemas aparecen cando queremos utilizar a variable global dentro da función, ou cando queremos utilizar a variable local no resto do programa, fora da función.

No seguinte programa temos unha variable global e outra local:

def funcion_con_variable(): #podemos poñer y como parámetro, pero de momento non é necesario
    y = 'Eu son local'

x = 'Eu son global'
 

Este programa de momento no fai nada. Imos imprimir os valores das variables. Temos varias posibilidades:

Descrición Código Saída
Imprimir variable global fora e variable local dentro

Non usamos parámetro

 


Non imprime y

 

Por que non imprime a variable y?. Pois por que non temos chamada á función. Imos modificalo:

Descrición Código Saída
Imprimir variable global fora e variable local dentro

 

 

Imprimir variable global dentro da función

 

 

Imprimir variable local fora da función

 

 

No último caso a variable local y non pode utilizarse fora da función, pero a variable global si pode utilizarse dentro da función. Para obter o valor de y fora da función teremos que utilizar return, tal e como vimos máis arriba no apartado de argumentos e retornos.

Variables co mesmo nome

Que sucede se as dúas variables teñen o mesmo nome (cousa habitual se copiamos código doutro programa)?. Pois que temos dúas variables co mesmo nome, unha local que só funciona dentro da función cando lle damos un valor. Vexamos posibilidades:

Descrición Código Saída
Variable global e local co mesmo nome, unha dentro e outra fora

 


No problem

 

Chamada a variable global dentro de función

 


Por que da erro?

 

É fundamental entender que x global está fora da función, e unha función sen parámetros utiliza varibales locais, que están dentro da función. Cando Python chama á función vai coller x local e se atopa con que non ten valor (tenno máis abaixo), Esta é razón pola que non está aconsellado utilizar variables globais, interfiren coas locais se teñen o mesmo nome. Se x non tivese valor dentro da función, o intérprete de comando buscaría o valor de x fora e atoparía o valor global.

COMO MODIFICAR VARIABLES GLOBAIS DENTRO DE FUNCIÓNS: GLOBAL KEYWORD

O normal nos programas sinxelos é que teñamos datos en variables globais, fagamos funcións para modificalos (é decir, as variables globais son parámetros) e queramos obter valores de saída da función. Vexamos que o máis probable é que teñamos problemas e que unha posible solución é utilizar a palabra reservada por Python (keyword) global para identificar como global a unha variable dentro dunha función:

Descrición Código Saída
Variable global como parámetro de función

 


No problem

 

Variable global que intentamos modificar dentro de función e non funciona

 


Por que da erro?

 

Variable global que modificamos dentro de función

Uso do keyword global

 

 

Pode ser necesario reflexionar sobre por que na función utilizamos como argumento a y, e logo na función non aparece. Se utilizaramos x como argumento daría erro.

VARIABLES NONLOCAIS E FUNCIÓNS ANIÑADAS: NONLOCAL KEYWORD

A medida que aumente a complexidade do algoritmo pode ser necesario ter funcións aniñadas. Dende Python 3 temos a posibilidade de crear e usar variables non locais, que se usan na subfunción e reciben o valor na función (non son globais, pero tampouco locais de todo).

Descrición Código Saída
Función aniñada con variable local

x é global e logo 2 veces local

 

 

Función aniñada con variable non local

Dentro da subfunción, x é non local, colle o valor da x na función e modifica o seu valor