首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >正在更新全局变量

正在更新全局变量
EN

Stack Overflow用户
提问于 2015-09-03 05:04:58
回答 3查看 58关注 0票数 0
代码语言:javascript
复制
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。

EN

回答 3

Stack Overflow用户

发布于 2015-09-03 05:15:07

看起来您正在修改相同的字典,解释器的行为是正确的。

代码语言:javascript
复制
>>> 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}

如果你真的需要一个单独的字典,你必须创建一个副本。

票数 0
EN

Stack Overflow用户

发布于 2015-09-03 08:56:03

这是由于的别名造成的。print active_trains_trial is active_trains应该打印True,尽管我希望您希望它打印False。这可以通过更改以下语句来修复

代码语言:javascript
复制
active_trains_trial = active_trains 

代码语言:javascript
复制
active_trains_trial = active_trains.copy()

进一步解释:

python中有两种对象:不可变对象和可变对象。不能更改不可变对象的值。不可变对象包括数值、字符串和元组等。

python的标识符不是变量,而是指向对象的简单名称。您不能更改不可变对象本身的值,但可以更改标识符所指向的对象。例如:

代码语言:javascript
复制
var = 3
var = 4

不更改int对象3的值,而是将标识符var重新分配给int对象4

别名是指为相同的对象指定不同的名称。

代码语言:javascript
复制
var1 = 3
var2 = 3

是为不可变对象3设置别名的示例。var1var2都是同一个对象,可以通过测试id是否相同来证明这一点。在python中,这可以通过两种方式完成:print var1 is var2print id(var1) == id(var2)。这两条语句都应该打印True

但是,此特定示例仅适用于不可变对象。一个适用于可变和不可变对象的示例如下:

代码语言:javascript
复制
var1 = <object>
var2 = var1

别名对于imutable对象始终是安全的,因为对象本身的值永远不会意外更改。例如:

代码语言:javascript
复制
var1 = 3
var2 = var1
var2 = 4
print var1
print var2
print var1 is var2

将产生输出

代码语言:javascript
复制
3
4
False

请注意var1 的值是如何改变的,而不是。

可变对象的值另一方面,可以被改变。可变对象包括列表和字典等。

代码语言:javascript
复制
L1 = [1, 2]
L2 = [1, 2]
L3 = L1
print L1 == L2
print L1 is L2
print L1 is L3

将产生输出

代码语言:javascript
复制
True
False
True

因为尽管L1L2具有相同的值,但它们不是相同的对象。而L3被分配给去 L1的对象,因此它们是同一个对象。

可变对象的别名可能是非常危险的。这样做的原因是,如果您使用对象的某个标识符更改对象的值,则所有其他标识符的值也将更改。

代码语言:javascript
复制
L1 = [1, 2, 3]
L2 = L1
L2 = [1, 2]
print L1
print L2
print L1 is L2

将产生输出

代码语言:javascript
复制
[1, 2]
[1, 2]
True

注意L1 的值是如何改变的。这是因为L1L2只是同一个可变对象的别名。

这可以通过创建对象的副本来避免。对于列表,可以这样做:L1 = <list>[:],对于字典,可以这样做:d1 = <dict>.copy()

代码语言:javascript
复制
L1 = [1, 2, 3]
L2 = L1[:]
L2 = [1, 2]
print L1
print L2
print L1 is L2

生成输出

代码语言:javascript
复制
[1, 2, 3]
[1, 2]
False

注意L1的值没有改变,而且L1和L2不是同一个对象。

票数 0
EN

Stack Overflow用户

发布于 2015-09-03 13:17:54

我设法找到了问题所在。

当创建字典的副本时,就是在创建映射的副本,而不是创建所引用的对象的副本。为了解释清楚,当我检查active_trains_local是否是active_trains时,它被证明是假的,因为它是active_trains的浅表副本。然而,active_trains_localperformer是active_trainsperformer。最后,我编写了一个duplicate_registery函数,它创建了一个字典,迭代了active_trains,并填充了新的字典。

代码语言:javascript
复制
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 (来自集合模块)。所以,

代码语言:javascript
复制
for name,dataset in self.active_trains.iteritems():
        duplicate_active_trains[name] = copy(dataset)

不起作用,因为它制作了一个“数据集”的浅拷贝,但即使在这个浅拷贝中,dataset.MR和dataset.OR也引用了原始数据集引用的同一对象。

学到的教训:浅层复制字典,浅层复制映射。您最终得到的重复映射仍然引用相同的对象。特别感谢@Thomson

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32363082

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档