(NameError: global name is not defined)将列表传递给函数时出现错误



很抱歉发了这么长的代码。我提取了生成和使用列表lower_lip_under_upper_list_plist的代码部分。链接使用此列表的函数时出现错误。generate_t_u()函数在time()函数内部被调用,但time()函数不会识别这个列表,因为它没有被传递到那里。但是如果我把它传递给这个函数,那么我也必须在main中做一些改变。还是会得到相同的误差。

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:全局名称'lower_lip_under_upper_list_plist'没有定义。

这个错误在time()函数的lower_lip_under_upper_list_bezier(0, lower_lip_under_upper_list_plist[i], lower_lip_under_upper_list_plist[i + 1])行。

考虑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。包含行号将有助于您(和我们)集中在问题上。

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没有绑定在那里——如果这指的是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应该可以消除对全局变量的需求。它还将最大限度地减少参数的数量,并让您专注于以干净和模块化的方式实现算法。

最新更新