Python作业调度回溯求解器报错:AttributeError与TypeError求助
作业调度回溯求解器的两类错误修复方案
错误原因分析与修复
1. AttributeError: 'str' object has no attribute 'variables'
根本原因:类的实例方法必须将self作为第一个参数,但你在check_constraint方法中把self放在了第三个参数位置。调用实例方法时,Python会自动将当前实例作为第一个参数传入,导致参数错位:
- 方法定义中的
arg1实际接收了self实例 arg2接收了var1(字符串)self接收了var2(字符串)
于是访问self.variables时,self是字符串类型,自然没有variables属性。
修复代码:
调整check_constraint的参数顺序,把self放在首位:
def check_constraint(self, arg1, arg2, assignment) -> bool: if (arg1 not in assignment) or (arg2 not in assignment): return True constraint = self.constraints.constraints[arg1][arg2] if constraint[1] == 0: return assignment[arg2] >= assignment[arg1] + constraint[0] if constraint[1] == 1: return assignment[arg1] + constraint[0] <= assignment[arg2] if constraint[1] == 2: return (assignment[arg1] + constraint[0] <= assignment[arg2]) or (assignment[arg2] + constraint[0] <= assignment[arg1])
同时保持调用方式不变:
result = self.check_constraint(var1, var2, assignment)
2. TypeError: 参数数量不匹配
根本原因:你尝试手动传入self到check_constraint,但Python实例方法会自动传递self作为第一个参数,导致实际传入的参数数量比方法定义多1个。
修复方式:
删除调用时手动传入的self,保持调用为:
result = self.check_constraint(var1, var2, assignment)
同时确保方法定义的参数顺序正确(如上面的修复)。
其他需要修复的方法参数问题
你的代码中还有多个实例方法存在self参数位置错误的问题,一并修复:
removeDomains方法
原定义:
def removeDomains(new_assignment, var,self):
修复后:
def removeDomains(self, new_assignment, var): removeddomains = {} for var1 in self.constraints.constraints[var]: constraint = self.constraints.constraints[var][var1] if constraint[1] == 0: intervallo_da_rimuovere = range(1, new_assignment[var] + 1 - constraint[0]) nuovo_dominio = list(self.variables[var1]) nuovo_dominio = list(filter(lambda x: x not in intervallo_da_rimuovere, nuovo_dominio)) self.variables[var1] = range(nuovo_dominio[0], nuovo_dominio[-1] + 1) removeddomains[var1] = intervallo_da_rimuovere if constraint[1] == 1 or constraint[1] == 2: intervallo_da_rimuovere = range(1, new_assignment[var] + 1 + constraint[0]) nuovo_dominio = list(self.variables[var1]) nuovo_dominio = list(filter(lambda x: x not in intervallo_da_rimuovere, nuovo_dominio)) self.variables[var1] = range(nuovo_dominio[0], nuovo_dominio[-1] + 1) removeddomains[var1] = intervallo_da_rimuovere return removeddomains
调用时改为:
tmp = self.removeDomains(new_assignment, var)
putRemovedDomains方法
原定义:
def putRemovedDomains(tmp, var,self):
修复后:
def putRemovedDomains(self, tmp, var): for var1 in self.constraints.constraints[var]: lista1 = list(tmp[var1]) lista2 = list(self.variables[var1]) lista_unione = lista1 + lista2 lista_unione.sort() self.variables[var1] = range(lista_unione[0], lista_unione[-1] + 1)
调用时改为:
self.putRemovedDomains(tmp, var)
backtracking_search方法调用
原代码中递归调用时手动传了self:
result = self.backtracking_search(self, new_assignment)
修复后:
result = self.backtracking_search(new_assignment)
额外潜在问题修复
checkAllconstraints中的循环错误:原代码for var1,var2 in self.constraints.constraints:会遍历字典的键,导致解包错误,应该遍历所有约束对:
def checkAllconstraints(self, assignment) -> bool: for var1 in self.constraints.constraints: for var2 in self.constraints.constraints[var1]: result = self.check_constraint(var1, var2, assignment) if not result: return False return True
__init__中的约束实例化:如果constraint类和当前类在同一文件,应该改为self.constraints = constraint(),而不是constrs.constraint()(除非constrs是导入的模块)。
内容的提问来源于stack exchange,提问作者Babboboncia
相关产品推荐
相关产品推荐

