На този кодов фрагмент:
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()
Съществуват и редица други потенциални решения, но повечето от тях ще доведат до неочаквано поведение.