函数未传入原变量却修改原变量的原因及解决方法
问题原因
- 赋值只是引用传递:
all_routes = routes并没有创建新的列表,只是让all_routes和routes指向内存中同一个列表对象。函数里对all_routes的修改,本质就是修改原routes指向的对象。 - 浅拷贝无效:如果只是用
list.copy()或者all_routes = routes.copy(),这属于浅拷贝——只会复制外层列表,但里面的子列表还是和原列表共享引用。函数里修改all_routes[k](也就是子列表)的操作,依然会直接影响原routes里的对应子列表。 - 关于字典
dists:你代码里写的distances = dist应该是笔误(原变量是dists),而且函数里只读取了distances的内容,没有修改字典本身,所以原dists其实没被改动,可能是你混淆了变量名。
解决方法
有两种可靠的方式避免修改原变量:
方法一:在函数内部使用深拷贝处理输入
修改calculate_cost函数,先对传入的all_routes做深拷贝,再操作拷贝后的对象,这样完全不影响原数据:
import copy def calculate_cost(distances, all_routes): # 深拷贝输入的列表,避免修改原数据 routes_copy = copy.deepcopy(all_routes) cost = 0 for k in range(len(routes_copy)): routes_copy[k].insert(0,0) routes_copy[k].append(0) for k in range(len(routes_copy)): for i in range(len(routes_copy[k])-1): pair = (routes_copy[k][i], routes_copy[k][i+1]) cost += distances[pair] return cost
调用时直接传原变量即可,不需要额外处理:
cost = calculate_cost(dists, routes) print(cost)
方法二:调用函数前做深拷贝
如果不想修改函数,就在调用前对routes做深拷贝:
import copy all_routes = copy.deepcopy(routes) distances = dists # 字典如果只读取的话,直接赋值没问题,因为函数没修改字典 cost = calculate_cost(distances, all_routes) print(cost)
额外优化(可选)
函数里的循环可以简化,用生成器表达式计算cost,代码更简洁:
import copy def calculate_cost(distances, all_routes): routes_copy = copy.deepcopy(all_routes) for route in routes_copy: route.insert(0, 0) route.append(0) # 用生成器表达式累加所有路段的距离 return sum(distances[(route[i], route[i+1])] for route in routes_copy for i in range(len(route)-1))
内容的提问来源于stack exchange,提问作者Parseval
相关产品推荐
相关产品推荐

