def is_safe(self,requesting_train_name,requesting_train_priority,requested_resources):
# Initialize P1 & P0
# We need to maintain an AR.
performer = requesting_train_name
AR = set(filter(lambda x : G.node[x]['reservation'] <= requesting_train_priority, G.nodes()))
P1 = []
P0 = self.active_trains.keys()
active_trains_trial = self.active_trains.copy()
print active_trains_trial is self.active_trains
# Update AR. Remove all elements of requested resources from AR
AR.difference_update(set(requested_resources))
# Provisionally updating OR
print 'OR before update',self.active_trains[performer].OR
active_trains_trial[performer].OR.update(set(requested_resources))
print 'OR after update',self.active_trains[performer].OR“更新前的OR”和“更新后的OR”行应该给出相同的结果。这没发生过。不出所料,-- is --语句返回False。
发布于 2015-09-03 05:15:07
看起来您正在修改相同的字典,解释器的行为是正确的。
>>> active_trains = {'one':1, 'two':2}
>>> active_trains_trial = active_trains
>>> active_trains_trial
{'two': 2, 'one': 1}
>>> active_trains_trial['one'] = 1.5
>>> active_trains
{'two': 2, 'one': 1.5}如果你真的需要一个单独的字典,你必须创建一个副本。
发布于 2015-09-03 08:56:03
这是由于的别名造成的。print active_trains_trial is active_trains应该打印True,尽管我希望您希望它打印False。这可以通过更改以下语句来修复
active_trains_trial = active_trains 至
active_trains_trial = active_trains.copy()进一步解释:
python中有两种对象:不可变对象和可变对象。不能更改不可变对象的值。不可变对象包括数值、字符串和元组等。
python的标识符不是变量,而是指向对象的简单名称。您不能更改不可变对象本身的值,但可以更改标识符所指向的对象。例如:
var = 3
var = 4不更改int对象3的值,而是将标识符var重新分配给int对象4。
别名是指为相同的对象指定不同的名称。
var1 = 3
var2 = 3是为不可变对象3设置别名的示例。var1和var2都是同一个对象,可以通过测试id是否相同来证明这一点。在python中,这可以通过两种方式完成:print var1 is var2或print id(var1) == id(var2)。这两条语句都应该打印True。
但是,此特定示例仅适用于不可变对象。一个适用于可变和不可变对象的示例如下:
var1 = <object>
var2 = var1别名对于imutable对象始终是安全的,因为对象本身的值永远不会意外更改。例如:
var1 = 3
var2 = var1
var2 = 4
print var1
print var2
print var1 is var2将产生输出
3
4
False请注意var1 的值是如何改变的,而不是。
可变对象的值另一方面,可以被改变。可变对象包括列表和字典等。
L1 = [1, 2]
L2 = [1, 2]
L3 = L1
print L1 == L2
print L1 is L2
print L1 is L3将产生输出
True
False
True因为尽管L1和L2具有相同的值,但它们不是相同的对象。而L3被分配给去 L1的对象,因此它们是同一个对象。
可变对象的别名可能是非常危险的。这样做的原因是,如果您使用对象的某个标识符更改对象的值,则所有其他标识符的值也将更改。
L1 = [1, 2, 3]
L2 = L1
L2 = [1, 2]
print L1
print L2
print L1 is L2将产生输出
[1, 2]
[1, 2]
True注意L1 的值是如何改变的。这是因为L1和L2只是同一个可变对象的别名。
这可以通过创建对象的副本来避免。对于列表,可以这样做:L1 = <list>[:],对于字典,可以这样做:d1 = <dict>.copy()
L1 = [1, 2, 3]
L2 = L1[:]
L2 = [1, 2]
print L1
print L2
print L1 is L2生成输出
[1, 2, 3]
[1, 2]
False注意L1的值没有改变,而且L1和L2不是同一个对象。
发布于 2015-09-03 13:17:54
我设法找到了问题所在。
当创建字典的副本时,就是在创建映射的副本,而不是创建所引用的对象的副本。为了解释清楚,当我检查active_trains_local是否是active_trains时,它被证明是假的,因为它是active_trains的浅表副本。然而,active_trains_localperformer是active_trainsperformer。最后,我编写了一个duplicate_registery函数,它创建了一个字典,迭代了active_trains,并填充了新的字典。
def duplicate_registery(self):
duplicate_active_trains = {}
for name,dataset in self.active_trains.iteritems():
duplicate_active_trains[name] = train_data(copy(dataset.MR),copy(dataset.OR))
return duplicate_active_trains本例中的值是namedtuples (来自集合模块)。所以,
for name,dataset in self.active_trains.iteritems():
duplicate_active_trains[name] = copy(dataset)不起作用,因为它制作了一个“数据集”的浅拷贝,但即使在这个浅拷贝中,dataset.MR和dataset.OR也引用了原始数据集引用的同一对象。
学到的教训:浅层复制字典,浅层复制映射。您最终得到的重复映射仍然引用相同的对象。特别感谢@Thomson
https://stackoverflow.com/questions/32363082
复制相似问题