将列表传递给函数引发(NameError: global name is not defined)错误
抱歉发了这么长的代码。我提取了生成和使用列表 lower_lip_under_upper_list_plist
的部分代码。现在在使用这个列表的地方出现了函数链接错误。generate_t_u()
函数是在 time()
函数里面调用的,但 time()
函数无法识别这个列表,因为它没有被传递进去。如果我把它传进去,那么主程序也得做相应的修改。这样一来,我又会遇到同样的错误。
def time(transcriptionFile) :
""" This function changes the time values in secs from the transcription file and keeps a list of start time for each phoneme. """
with open("transcriptions.txt", "r") as tFile :
timeList = []
t_u = 0.0
for line in tFile :
li = line.split()
if li :
start_time = (int(li[0]) / 10000000.)
timeList.append(start_time)
#print timeList
generate_t_u(timeList, lower_lip_under_upper_list_plist)
def generate_t_u(timeList, lower_lip_under_upper_list_plist)
""" It generates the regular time intervals t(u) values for sampling. """
i = 0
while i < len(timeList) - 1 :
# if the number is in the range
# do the calculations and move to the next number
if t_u > timeList[i] and t_u < timeList[i + 1] :
#print "\n The t_u value:", t_u, 'is between',
#print "start:", timeList[i], " and end: ", timeList[i+1]
poly = poly_coeff(timeList[i], timeList[i + 1], t_u)
Newton(poly, lower_lip_under_upper_list_plist[i], lower_lip_under_upper_list_plist[i + 1])
t_u = t_u + 0.04 # regular time interval
# if the number is at the lower boundary of the range, no need of calculation as u = 0
elif t_u == timeList[i] :
#print "\n The t_u value:", t_u, 'is on the boundary of',
#print "start:", timeList[i], " and end: ", timeList[i+1]
#print "u : 0"
lower_lip_under_upper_list_bezier(0, lower_lip_under_upper_list_plist[i], lower_lip_under_upper_list_plist[i + 1])
t_u = t_u + 0.04 # regular time interval
# if the number is at the upper boundary of the range, no need of calculation as u = 1
elif t_u == timeList[i + 1] :
#print "\n The t_u value:", t_u, 'is on the boundary of',
#print "start:", timeList[i], " and end: ", timeList[i+1]
#print " u : 1"
lower_lip_under_upper_list_bezier(1, lower_lip_under_upper_list_plist[i], lower_lip_under_upper_list_plist[i + 1])
t_u = t_u + 0.04 # regular time interval
# if the number isn't in the range, move to the next range
else :
i += 1
def Newton(poly, p0, p3) :
""" Newton's method for finding the root of a polynomial. Here the root is the 'u' value"""
poly_diff = poly_differentiate(poly)
counter = 0
epsilon = 0.000000000001
x = 0.5 # initial guess value
while True:
x_n = x - (float(poly_substitute(poly, x)) / poly_substitute(poly_diff, x))
counter += 1
if abs(x_n - x) < epsilon :
break
x = x_n
#print "\tIteration " , counter , " : ", x_n
print "u:", (x_n)
lower_lip_under_upper_list_bezier(x_n, p0, p3)
def param_lists_separate(pList) :
""" Separating the parameter values of each feature into individual lists """
v = [[inner[1][i] for outer in pList for inner in outer]
for i in range(len(pList[0][0][1]))]
lower_lip_under_upper_list_plist = v[0]
lips_part_plist = v[1]
lips_spread_plist = v[2]
jaw_open_plist = v[3]
lips_round_plist = v[4]
return lower_lip_under_upper_list_plist
def lower_lip_under_upper_list_bezier(x_n, p0, p3) :
""" Calculating sampling points using rational bezier curve equation"""
u = x_n
p1 = p0
p2 = p3
lower_lip_under_upper_list_p_u = math.pow(1 - u, 3) * p0 + 3 * u * math.pow(1 - u, 2) * p1 \
+ 3 * (1 - u) * math.pow(u, 2) * p2 + math.pow(u, 3) * p3
lower_lip_under_upper_list_p_u = lower_lip_under_upper_list_p_u * w
d = math.pow(1 - u, 3) * w + 3 * u * w * math.pow(1 - u, 2) + 3 * (1 - u) * w * math.pow(u, 2) + math.pow(u, 3) * w
lower_lip_under_upper_list_p_u = lower_lip_under_upper_list_p_u / d
print "\n p(u) values for the feature lower lip under upper list \n"
print "p(u): ", lower_lip_under_upper_list_p_u
return lower_lip_under_upper_list_p_u
if __name__ == "__main__" :
time("transcriptions.txt")
错误信息是:
NameError: global name 'lower_lip_under_upper_list_plist' is not defined.
这个错误出现在 time()
函数中的这一行:lower_lip_under_upper_list_bezier(0, lower_lip_under_upper_list_plist[i], lower_lip_under_upper_list_plist[i + 1])
。
2 个回答
你觉得 lower_lip_under_upper_list_plist
应该作为 generate_t_u
的返回值吗?试着把 generate_t_u
改成这样:
def generate_t_u(time_list):
lower_lip_under_upper_list_plist = []
# ... the function remains the same
return lower_lip_upper_list_plist
我不太确定 param_lists_separate
是在哪里被调用的,但看起来里面的绑定也应该是全局的。generate_t_u
里也有类似的问题,因为 t_u
没有在这里绑定——如果这个 t_u
指的是 time
里的 t_u
,那么它可能应该作为一个参数传入。如果你有很多相关的绑定和方法来处理这些数据,那么你可能应该考虑创建一个类,把数据和操作结合在一起。
考虑改成下面这样的做法:
class NewtonsMethod(object):
def __init__(self, file_name):
# change global names into properties of ``self``
self.lower_lip_under_upper_list_plist = []
self.lips_part_plist = []
self.lips_spread_plist = []
self.jaw_open_plist = []
self.lips_round_plist = []
self.t_u = 0.0
self.time_list = []
# initialize from the data file
with open(file_name) as file_ref:
for line in file_ref:
data = line.split()
if data:
start_time = (int(data[0]) / 10000000.0)
self.time_list.append(start_time)
def _lower_lip_under_upper_list_bezier(self, x_n, point):
(u, p1, p2) = (x_n, self.lower_lip_under_upper_list_plist[point],
self.lower_lip_under_upper_list_plist[point + 1])
# if lower_lip_under_upper_list_p_u is used elsewhere, then it
# might make sense to change it to a property
lower_lip_under_upper_list_p_u = ...
return lower_lip_under_upper_list_p_u
def _generate_t_u(self):
(i, t_u) = (0, 0.0)
while i < len(self.time_list) - 1:
if t_u > self.time_list[i] and t_u < time_list[i + 1]:
poly = poly_coeff(self.time_list[i], self.time_list[i + 1], t_u)
self._apply_newton(poly, i)
elif t_u == self.time_list[i]:
self._lower_lip_under_upper_list_bezier(0, i)
t_u += 0.04
elif t_u == self.time_list[i + 1]:
self._lower_lip_under_upper_list_bezier(1, i)
t_u += 0.04
else:
i += 1
def _apply_newton(self, poly, point):
poly_diff = poly_differentiate(poly)
(epsilon, x) = (0.0000000001, 0.5)
while True:
x_n = x - (...)
if abs(x_n - x) < epsilon:
break
x = x_n
self._lower_lip_under_upper_list_bezier(x_n, point)
面向对象编程的一个基本原则是把算法和它们处理或需要的数据捆绑在一起。你可以在这里应用这个想法。你的全局绑定会变成对象的属性,这样在实例方法中总是可以通过 self
访问它们。正如你可能注意到的那样,传递 lower_lip_under_upper_list_plist
这样的值就不再必要了。你只需要传递列表中的索引,因为列表本身是对象的一个属性。
把你的算法重构成一个 class
应该能消除到处使用全局变量的需要。这也会减少参数的数量,让你能更专注于以干净和模块化的方式实现算法。
考虑一下在 time
函数中的这一行:
def time(transcriptionFile) :
...
generate_t_u(timeList, lower_lip_under_upper_list_plist)
这里的 lower_lip_under_upper_list_plist
在 time
函数里没有定义,所以 Python 会去全局范围找这个变量。结果在全局范围也找不到,于是 Python 就抛出了一个 NameError
错误,意思是这个变量 lower_lip_under_upper_list_plist
没有被定义。
顺便提一下,错误信息中会包含一个行号,指明是哪个行导致了 NameError
。这个行号会帮助你(还有我们)更快找到问题所在。