python list comprehension错误:未定义全局名称

时间:2014-03-17 01:41:07

标签: python list-comprehension nameerror

我遇到了一个奇怪的问题。错误消息是: 全球名称' id2tag'没有定义。 我已阅读此帖Accessing class variables from a list comprehension in the class definition。但显然id2tag不是类变量。代码如下所示。

class evaluater:
    def evaluate_topk(self, ground_truth_dict, predicted_dict, setting_name, setting, data,
                      eval_root_dir = './', file_name = 'result',k = 5,output_entry = 100 ):
        #this part of code is not relevant
        recall = {}
        for key, ground_truth in ground_truth_dict.items():
            recall[key] = recall_at_k(ground_truth, predicted_dict[key])

        mean_recall = np.mean([value for key,value in recall.items()])

        filepath = eval_root_dir + file_name
        if not os.path.exists(os.path.dirname(filepath)):
            os.makedirs(os.path.dirname(filepath))        

        #HERE IS WHERE id2tag DEFINED
        id2tag = {row[0]:row[1] for row in data[config.TYPE_TAG] }
        with open( filepath , 'a' ) as file:
            for itemid in sorted(ground_truth_dict.keys())[1:100]:
                file.write(str(itemid) + '\n')

                file.write('gnd:'+str([id2tag[id] for id in ground_truth_dict[itemid]] ) + '\n')
                file.write('prt' + str([ id2tag[id] for id in predicted_dict[itemid]]) + '\n' )
                #if i use the below code instead, then would be fine
                #gnd_tags = []
                #prt_tags = []
                #for id in ground_truth_dict[itemid]:
                #    gnd_tags.append(id2tag[id])
                #    
                #for id in predicted_dict[itemid]:
                #    prt_tags.append(id2tag[id])
                #    
                #file.write('gnd:'+str( gnd_tags ) + '\n')
                #file.write('prt' + str(prt_tags) + '\n' )

        return mean_recall

2 个答案:

答案 0 :(得分:1)

复杂嵌入代码中的语法错误。如果您将一行代码拆分为三个,我认为您的奇怪问题将会消失:

# Change this line 
id2tag = {row[0]:row[1] for row in data[config.TYPE_TAG]}

# Change to this
id2tag = {}
for row in data[config.TYPE_TAG]:
    id2tag[row[0]] = row[1]

顺便说一句:我建议不要以你的方式使用嵌入式for x in list_var,这对其他代码阅读器来说并不容易阅读和理解。

答案 1 :(得分:0)

这是一个奇怪的问题。我在pdb中的py.test中调试类函数的命名空间时遇到了它。在pdb之外没有错误。

(Pdb) lines=["oneline",2,3,4,5]
(Pdb) ip_dict = dict( ( lines[i], lines[i+1] ) for i in range(0,len(lines),2) )
*** NameError: global name 'lines' is not defined
(Pdb) for i in range(0,len(lines),2): print "%d=%s" % (i,lines[i])
0=oneline
2=3
4=5

(Pdb) self
<Docker-sanity_regression.SANITY testMethod=test_SANITY_002_####_container>

为了简化问题,这里有一个例子。

lines=["oneline",2,3,4,5]
ip_dict = dict( ( lines[i], lines[i+1] ) for i in range(0,len(lines),2) )
print ip_dict

这适用于python 2.4。和python 2.7。 将dict集嵌入类func中:

class Test:
    def __init__(self):
        print "init"
        self.ip_dict = {}

    def setDict(self):
        lines=["oneline",2,3,4,5]
        self.ip_dict = dict( ( lines[i], lines[i+1] ) for i in range(0,len(lines),2) )
        print self.ip_dict

foo = Test()
foo.setDict()

这对python 2.4也适用。和python 2.7。

所以我认为在某些版本的python和pdb中存在一个有趣的命名空间问题,对于这种类型的理解。 编辑:是的。 pdb的已知问题。感谢https://stackoverflow.com/users/396967/kynan的解释。 https://bugs.python.org/issue21161标题:列表推导没有在python3中的pdb中看到局部变量