/ / Работа с глобална променлива вътре в Python функция - python

Работа с глобална променлива вътре в функция python - python

На този кодов фрагмент:

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]

Получавам съобщение за грешка:

UnboundLocalError: local variable "puntosX" referenced before assignment

И така знам, че същото ще се случи и с другите две променливи. Какво мога да направя това е външното taylorVazquezпроменливите, с които манипулирам във вътрешната функция, с други думи, искам задачите да работят и за външния обхват

Отговори:

2 за отговор № 1

Когато присвоите стойност на променлива в aпри условие, че променливата се приема за локална за този обхват. В зависимост от това кой Python използвате, трябва или да използвате нелокален (Python 3) или да предавате стойностите в параметри (Python 2).

Ето го 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]

в 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 ще НЕ работят в тази ситуация, тъй като се позовавате на имената на ограждаща функция.

Още едно нещо, МОЖЕТЕ да се опитвате да назначите новистойности към имената в обхвата на приложение. Настоящата ви тактика няма да работи, тъй като присвоявате нови обекти на тези имена в рамките на най-вътрешната функция. (Разбирането на списък създава нови списъци.) Ако трябва да запазите новите стойности, ще трябва (например) да върнете тези стойности в обхвата и да превъзложите вашите оригинални имена на новите стойности. Например в Python 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

за разлика от global, не можете да зададете нови стойности на тези имена и да ги задържите за обхващащия обхват.


2 за отговор № 2

Ако зададете на променлива в Python функция,интерпретаторът приема, че е локална променлива. Всички други употреби на тази променлива също се приемат за местни, дори и такива, които идват преди заданието. Затова получавате изключение за това local variable "puntosX" referenced before assignment.

Има няколко възможни решения.

Единият е да се обяви променливата да бъде global (или в Python 3, nonlocal ако е локална променлива в заграждаща функция).

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]

Друг вариант е да се мутира променливата на място, вместо да се преназначава. Например, можете да използвате list.append и list.__setitem__ в списък, без никога да правите локално позоваване на него.

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

# etc...

Последната опция е да разгънете функциите си и да предавате аргументи и връщате стойности, вместо да разчитате на вложените пространства от имена, за да направите вашите стойности достъпни. Например:

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

# then later
puntosX = toFloat(puntosX)

1 за отговор № 3

Можете да получите достъп до променливата добре, проблемът тук е, че в Python2 няма начин да пренаредите променливата. (PEP-227).

Всъщност той е бил адресиран в Python 3 и вие можете да маркирате променливите си като nonlocal, но това не е голям комфорт, ако все още използвате Python 2.

Можете да го заобиколите, като направите нещо подобно:

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

Съществуват и редица други потенциални решения, но повечето от тях ще доведат до неочаквано поведение.