2013-07-26 63 views
3

如何用另一个对象替换所有python对象?用另一个对象替换一个python对象

我有两个类,SimpleObjectFancyObject。我创建了一个SimpleObject,并有几个引用。现在我想创建一个FancyObject,并使所有这些引用指向新对象。

a = SimpleObject() 
some_list.append(a) 
b = FancyObject() 

a = b是不是我想要的,它只是改变什么点。我阅读以下内容会有效,但不会。我得到一个错误“属性__dict__是不可写”:

a.__dict__ = b.__dict__ 

我要的是(伪C)相当于:

*a = *b 

我知道这是哈克,但有什么办法完成这个?

+0

所以,你想改变什么数据被存储在'了'存储的地方吗?我会在午餐后发布答案。 – pradyunsg

+0

@Schoolboy是的。基本上我已经把一个简单的对象放在了一个,并且当需要出现时想(懒惰地)将它提升到更复杂的对象b。 a和b有相同的接口,所以使用它们的代码应该能够处理这个。 – jdm

回答

0

没有办法。它会让你改变不可变的对象并导致各种各样的混乱。

x = 1 
y = (x,) 
z = {x: 3} 
magic_replace(x, [1]) 
# x is now a list! 
# The contents of y have changed, and z now has an unhashable key. 

x = 1 + 1 
# Is x 2, or [1, 1], or something stranger? 
+0

好吧,'y','z'的内容不会改变,因为它们指的是'x'早些时候指的是什么。唯一改变的是'x'指的。 (如果我错了,纠正我,因为我不知道C)。 – pradyunsg

+1

如果你只想改变'x'的名字,'x = whatever'就是你所追求的。如果你想魔术般地替换对象'x'是指一个新对象,那么在使用旧对象(包括字典和元组)的任何地方都必须可见。 – user2357112

+0

@Schoolboy但这就是OP所要求的:不只是替换'x',而是所有其他引用同一个对象的名字。如果你没有意识到,在Python中'1'是一个对象,在主要的Python实现中,所有使用值'1'的东西都只是引用同一个对象。 – Duncan

1

你可以把这个对象放在独立模块的全局命名空间中,而不是在需要的时候给猴子打补丁。

objstore.py

replaceable = object() 

sample.py

import objstore 

b = object() 

def isB(): 
    return objstore.replaceable is b 

if __name__ == '__main__': 
    print isB()#False 
    objstore.replaceable = b 
    print isB()#True 

附:依靠猴子补丁是设计不佳的一个症状

1

我刚刚发现this。它的replace_all_refs函数似乎工作得很好。

+2

你应该在你的帖子中包含更多关于你链接到的内容的信息。 – Michelle

0

你有多种选择:

  1. 设计这个从一开始,使用Facade模式(即在主代码中的每个对象是别的东西的代理),或单可变容器(即每个变量都包含一个列表;您可以通过任何这样的参考来更改列表的内容)。优点是它可以与语言的执行机构一起工作,并且相对容易地从受影响的代码中发现。下行:更多代码。
  2. 始终引用相同的单个变量。这是以上的一个实施。清洁,没有什么奇特的,在代码中清晰。我会推荐这一点。
  3. 使用debug,gc和introspection功能查找符合条件的每个对象,并在运行时更改变量。缺点是在代码执行过程中变量的值会发生变化,而不会从受影响的代码中发现变量的值。即使这种改变是原子的(消除了一类错误),因为这可以在执行代码后改变变量的类型,这些代码确定这个值是不同类型的,所以引入了在该代码中不能合理预期的错误。例如

    a = iter(b) # will blow up if not iterable 
    [x for x in b] # before change, was iterable, but between two lines, b was changed to an int. 
    

更巧妙,串和非字符串的序列之间进行区分时(因为串的限定特征是迭代他们也产生字符串,其本身可迭代),平坦化的结构的情况下,代码可能被破坏。

另一个答案提到pyjack它实现选项3.虽然它可能工作,它有所有提到的问题。这只适用于调试和开发。

0

充分利用可变对象,如列表。

a = [SimpleObject()] 
some_list.append(a) 
b = FancyObject() 
a[0] = b 

证明这个工程:

class SimpleObject(): 
    def Who(self): 
     print 'SimpleObject' 

class FancyObject(): 
    def Who(self): 
     print 'FancyObject' 

>>> a = [SimpleObject()] 
>>> a[0].Who() 
SimpleObject 
>>> some_list = [] 
>>> some_list.append(a) 
>>> some_list[0][0].Who() 
SimpleObject 
>>> b = FancyObject() 
>>> b.Who() 
FancyObject 
>>> a[0] = b 
>>> some_list[0][0].Who() 
FancyObject 
相关问题