/ / Praca ze zmienną globalną wewnątrz funkcji Pythona - python

Praca z globalną zmienną wewnątrz funkcji Pythona - python

W tym fragmencie kodu:

def taylorVazquez(fx,a,b,n,puntos):

puntosX = linspace(a,b,num=puntos)
aproxY = []
puntosY = []

def toFloat():
puntosX = [float(x) for x in puntosX]
aproxY = [float(y) for y in aproxY]
puntosY = [float(y) for y in puntosY]

Otrzymuję komunikat o błędzie:

UnboundLocalError: local variable "puntosX" referenced before assignment

I wiem, że tak samo stanie się z pozostałymi dwiema zmiennymi. Co mogę zrobić, to zewnętrzny taylorVazquez„s zmienne, którymi manipuluję w funkcji wewnętrznej, innymi słowy, chcę, aby zadania również działały w zakresie zewnętrznym

Odpowiedzi:

2 dla odpowiedzi № 1

Za każdym razem, gdy przypisujesz wartość do zmiennej w abiorąc pod uwagę zakres, zakłada się, że zmienna jest lokalna w tym zakresie. W zależności od tego, którego Pythona używasz, będziesz musiał użyć nonlocal (Python 3) lub przekazać wartości przy użyciu parametrów (Python 2).

Tutaj jest Python 2:

def toFloat(puntosX, aproxY, puntosY):  # now the names of the enclosing function can be passed to the toFloat function
puntosX = [float(x) for x in puntosX]
aproxY = [float(y) for y in aproxY]
puntosY = [float(y) for y in puntosY]

W Python 3:

def toFloat():
nonlocal puntosX, aproxY, puntosY  # the names now refer to the enclosing scope rather than the local scope
puntosX = [float(x) for x in puntosX]
aproxY = [float(y) for y in aproxY]
puntosY = [float(y) for y in puntosY]

global będzie NIE działa w tej sytuacji, ponieważ odwołujesz się do nazw funkcji obejmującej.

Jeszcze jedno, MOŻESZ próbować przypisać nowewartości do nazw w załączającym zakresie. Twoja obecna taktyka nie będzie działać, ponieważ przypisujesz nowe obiekty do tych nazw w najbardziej wewnętrznej funkcji. (Rozbudowane listy tworzą nowe listy). Jeśli chcesz zachować nowe wartości, musisz (na przykład) zwrócić te wartości do zakresu obejmującego i ponownie przypisać oryginalne nazwy do nowych wartości. Na przykład w Pythonie 2:

def taylorVazquez(fx,a,b,n,puntos):
puntosX = linspace(a,b,num=puntos)
aproxY = []
puntosY = []

def toFloat(puntosX, aproxY, puntosY):  # now the names of the enclosing function can be passed to the toFloat function
puntosX = [float(x) for x in puntosX]
aproxY = [float(y) for y in aproxY]
puntosY = [float(y) for y in puntosY]
return puntosX, aproxY, puntosY

puntosX, aproxY, puntosY = toFloat(puntosX, aproxY, puntosY)  # now you can reassign these names to the new values

w odróżnieniu global, nie możesz przypisać nowych wartości do tych nazw i zachować je dla zakresu obejmującego.


2 dla odpowiedzi nr 2

Jeśli przypisujesz zmiennej do funkcji Pythona,interpreter zakłada, że ​​jest to zmienna lokalna. Przyjmuje się, że wszystkie inne zastosowania tej zmiennej są lokalne, nawet te, które mają miejsce przed przypisaniem. Dlatego masz wyjątek local variable "puntosX" referenced before assignment.

Istnieje kilka możliwych rozwiązań.

Jednym z nich jest zadeklarowanie zmiennej jako global (lub w Pythonie 3, nonlocal jeśli jest to zmienna lokalna w funkcji obejmującej).

def taylorVazquez(fx,a,b,n,puntos):

puntosX = linspace(a,b,num=puntos)
aproxY = []
puntosY = []

def toFloat():
nonlocal puntosX, aproxY, puntosY # this fixes the UnboundLocalError

puntosX = [float(x) for x in puntosX]
aproxY = [float(y) for y in aproxY]
puntosY = [float(y) for y in puntosY]

Inną opcją jest mutacja zmiennej w miejscu, a nie jej ponowne przypisywanie. Na przykład możesz użyć list.append i list.__setitem__ na liście, nigdy nie robiąc lokalnego odniesienia do niej.

def toFloat():
for i, v in enumerate(puntosX):
puntosX[i] = float(v) # this calls puntosX.__setitem__, mutating it in place

# etc...

Ostatnią opcją jest odblokowanie funkcji i przekazanie argumentów oraz zwracanie wartości, zamiast polegania na zagnieżdżonych przestrzeniach nazw, aby udostępnić wartości. Na przykład:

def toFloat(lst):
return [float(v) for v in lst]

# then later
puntosX = toFloat(puntosX)

1 dla odpowiedzi nr 3

Możesz uzyskać dostęp do zmiennej w porządku, problemem jest to, że w Pythonie2 nie ma możliwości ponownego przypisania zmiennej. (PEP-227).

W Pythonie 3 zostało to w rzeczywistości zaadresowane i można oznaczyć zmienne jako nonlocal, ale to nie jest wielki komfort, jeśli nadal używasz Pythona 2.

Możesz obejść to, robiąc coś takiego:

def f1():
x = [1]
def f2():
x[0] = 2
f2()
print x[0]
f1()

Istnieje również wiele innych potencjalnych obejść, ale większość z nich spowoduje nieoczekiwane zachowanie.