全局变量正在更新

时间:2015-09-02 21:04:58

标签: python-2.7 namespaces

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。

3 个答案:

答案 0 :(得分:0)

看起来您正在修改相同的字典并且解释器的行为正常。

>>> 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}

如果您确实需要单独的字典,则必须创建副本。

答案 1 :(得分:0)

由于别名,这种情况正在发生。 print active_trains_trial is active_trains应打印True,但我希望您希望打印False。这可以通过更改语句

来解决
active_trains_trial = active_trains 

active_trains_trial = active_trains.copy()

进一步说明:

python中有两种对象: immutable mutable 不可变对象的值无法更改。不可变对象包括数值,字符串和元组等。

而不是变量,python有标识符,它们只是指向对象的名称。您无法更改不可变对象本身的值,但您可以更改标识符指向的对象。例如:

var = 3
var = 4

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

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

var1 = 3
var2 = 3

是对不可变对象3进行别名的示例。 var1var2都是同一个对象,可以通过测试来证明id是否相同。这可以在python中以两种方式完成:print var1 is var2print 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

因为虽然L1L2具有相同的,但它们相同的对象。虽然L3被指定为 L1的对象,但他们 是同一个对象。

别名可变对象可能非常危险。这样做的原因是,如果您使用其中一个标识符 all 其他标识符&#39;更改对象的值。价值也会发生变化。

L1 = [1, 2, 3]
L2 = L1
L2 = [1, 2]
print L1
print L2
print L1 is L2

将产生输出

[1, 2]
[1, 2]
True

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

可以通过创建对象的副本来避免这种情况。使用列表可以将其完成为: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不是同一个对象。

答案 2 :(得分:0)

我设法找到了问题所在。

当创建字典的副本时,可以创建映射的副本,而无需复制正在引用的对象。为了说明,当我检查active_trains_local是否为active_trains时,结果是假的,因为它是active_trains的浅表副本。但是,active_trains_local [执行者] active_trains [执行者]。我终于写了一个duplicate_registery函数,它创建了一个字典,在active_trains上迭代,并填充了新的字典。

-- file: ch05/PrettyJSON.hs
module PrettyJSON
    (
      renderJValue
    ) where

import Numeric (showHex)
import Data.Char (ord)
import Data.Bits (shiftR, (.&.))

import SimpleJSON (JValue(..))
import Prettify (Doc, (<>), char, double, fsep, hcat, punctuate, text,
                 compact, pretty

这种情况下的值是namedtuples(来自collections模块)。所以,

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

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

获得的经验:浅写复制字典,给出映射的浅表副本。您最终得到的重复映射仍然引用相同的对象。特别感谢@Thomson