计算PageRank时触发TypeError:float对象不可迭代,求解决
TypeError错误排查:检查字符串是否在列表中时提示"float对象不可迭代"
我在计算pagerank.txt中所有文档的单轮PageRank值时,运行代码触发了TypeError错误,错误出现在检查字符串是否存在于列表的语句中。我已经查阅过相关问题但没找到合适的解决方案。
原代码
def calc_pageranks(pagerank_file = "pagerank.txt", damping=0.9): pagerankScores = {} pagerankData = {} #dict of what files a file (the dict key) points to with open(pagerank_file, "r") as f: for row in f: row = row.split() pagerankScores.update({row[0]:1}) #set starting pagerank for documents if len(row) == 1: pagerankData.update({row[0]:None}) else: pagerankData.update({row[0]:row[1:]}) #pagerank graph for docName in pagerankData: pagerank = pagerankScores[docName] temp = 0 for val in pagerankData.values(): if val == None: pass else: if docName in val: temp += pagerank / len(val) pagerank = (1 - damping) + damping * temp pagerankData.update({docName:pagerank}) return pagerankScores, pagerankData
docName和val的初始类型示例:doc1.txt <class 'str'> ['doc2.txt', 'doc8.txt'] <class 'list'>
完整错误信息
/Library/Frameworks/Python.framework/Versions/3.9/bin/python3 /Users/MacSuperior/Desktop/Coding/IR_system/search_engine.py Traceback (most recent call last): File "/Users/MacSuperior/Desktop/Coding/IR_system/search_engine.py", line 99, in <module> print(calc_pageranks()) File "/Users/MacSuperior/Desktop/Coding/IR_system/search_engine.py", line 92, in calc_pageranks if docName in val: TypeError: argument of type 'float' is not iterable
pagerank.txt内容
doc1.txt doc2.txt doc8.txt doc2.txt doc1.txt doc2.txt doc9.txt doc3.txt doc4.txt doc4.txt doc1.txt doc10.txt doc5.txt doc6.txt doc6.txt doc7.txt doc1.txt doc8.txt doc9.txt doc10.txt doc9.txt doc10.txt doc10.txt doc9.txt
错误原因
问题出在遍历pagerankData.values()的过程中,你直接修改了pagerankData的内容——把原本存储**链接列表(或None)**的字典值替换成了计算后的float类型PageRank分数。第一次循环处理某个文档时,pagerankData里的大部分值还是列表/None,但执行pagerankData.update({docName:pagerank})后,后续遍历到这个文档的val时,它已经变成了float类型,此时再执行docName in val就会触发错误,因为float不是可迭代对象,无法用in判断成员关系。
修复方案
需要把存储链接关系的字典和存储计算后PageRank分数的字典分开,不要复用pagerankData存储结果。同时调整计算逻辑,单轮PageRank的计算应该基于初始的链接关系,而非边计算边修改数据源。
修复后的代码:
def calc_pageranks(pagerank_file = "pagerank.txt", damping=0.9): pagerankScores = {} linkGraph = {} # 单独存储文档的链接关系,全程不修改 with open(pagerank_file, "r") as f: for row in f: row = row.split() doc = row[0] pagerankScores[doc] = 1 # 初始化PageRank为1 if len(row) == 1: linkGraph[doc] = None else: linkGraph[doc] = row[1:] # 计算单轮PageRank newPagerank = {} num_docs = len(pagerankScores) base_score = (1 - damping) / num_docs # 基础分平均分配给所有文档 for target_doc in pagerankScores: temp = 0 for source_doc, links in linkGraph.items(): if links is None: # 无出链文档,把自身PageRank平均分给所有文档 temp += pagerankScores[source_doc] / num_docs elif target_doc in links: # 有出链且指向当前文档,按出链数量分配 temp += pagerankScores[source_doc] / len(links) # 计算最终分数:基础分 + 阻尼系数*贡献分 newPagerank[target_doc] = base_score + damping * temp return pagerankScores, newPagerank
关键修改点
- 拆分数据存储:用
linkGraph专门存储文档的链接关系,全程不修改,避免遍历过程中数据类型被篡改。 - 修正基础分计算:原代码中
(1 - damping)未平均分配给所有文档,不符合PageRank标准公式,改为(1 - damping)/num_docs。 - 处理无出链文档:原代码忽略了无出链文档的贡献,修复后将这类文档的PageRank平均分配给所有文档。
- 分离计算结果:用
newPagerank存储计算后的分数,不影响原始的链接关系数据。
内容的提问来源于stack exchange,提问作者MacSuperior
相关产品推荐
相关产品推荐

