Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jsf-2/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
将一个python对象替换为另一个python对象_Python_Python 2.7 - Fatal编程技术网

将一个python对象替换为另一个python对象

将一个python对象替换为另一个python对象,python,python-2.7,Python,Python 2.7,如何用另一个对象替换python对象 我有两个类,SimpleObject和FancyObject。我创建了一个SimpleObject,并对它进行了多次引用。现在我想创建一个FancyObject,并使所有这些引用指向新对象 a = SimpleObject() some_list.append(a) b = FancyObject() a=b不是我想要的,它只是改变了a指向的内容。我读到下面的内容会有用,但不会。我得到一个错误“属性不可写”: 我想要的是(pseudo-C)的等价物: 我知

如何用另一个对象替换python对象

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

a = SimpleObject()
some_list.append(a)
b = FancyObject()
a=b
不是我想要的,它只是改变了a指向的内容。我读到下面的内容会有用,但不会。我得到一个错误“属性不可写”:

我想要的是(pseudo-C)的等价物:


我知道这很麻烦,但有没有办法做到这一点?

没有办法。它会让你变异不可变的对象,并造成各种各样的肮脏

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?

您可以将该对象放在单独模块的全局命名空间中,然后在需要时对其进行修补

objstore.py

replaceable = object()
import objstore

b = object()

def isB():
     return objstore.replaceable is b

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

replaceable = object()
import objstore

b = object()

def isB():
     return objstore.replaceable is b

if __name__ == '__main__':
     print isB()#False
     objstore.replaceable = b
     print isB()#True
p.S.依赖猴子补丁是设计不良的症状

有一个功能
replace\u all\u refs
,它可以替换对内存中对象的所有引用

文档中的一个示例:

>>> item = (100, 'one hundred')
>>> data = {item: True, 'itemdata': item}
>>> 
>>> class Foobar(object):
...     the_item = item
... 
>>> def outer(datum):
...     def inner():
...         return ("Here is the datum:", datum,)
...     
...     return inner
... 
>>> inner = outer(item)
>>> 
>>> print item
(100, 'one hundred')
>>> print data
{'itemdata': (100, 'one hundred'), (100, 'one hundred'): True}
>>> print Foobar.the_item
(100, 'one hundred')
>>> print inner()
('Here is the datum:', (100, 'one hundred'))
调用replace_all_refs

>>> new = (101, 'one hundred and one')
>>> org_item = pyjack.replace_all_refs(item, new)
>>> 
>>> print item
(101, 'one hundred and one')
>>> print data
{'itemdata': (101, 'one hundred and one'), (101, 'one hundred and one'): True}
>>> print Foobar.the_item
(101, 'one hundred and one')
>>> print inner()
('Here is the datum:', (101, 'one hundred and one'))

您有许多选择:

  • 使用Facade模式(即主代码中的每个对象都是其他对象的代理)或单个可变容器(即每个变量都包含一个列表;您可以通过任何此类引用更改列表的内容),从一开始就进行设计。优点是它与语言的执行机制一起工作,并且相对容易从受影响的代码中发现。缺点:更多的代码
  • 始终引用同一个单一变量。这是上述方法的一个实现。干净,没有花哨,代码清晰。到目前为止,我会推荐这个
  • 使用debug、gc和内省功能查找满足条件的每个对象,并在运行时更改变量。缺点是变量的值在代码执行期间会发生变化,而不会从受影响的代码中发现。即使更改是原子性的(消除了一类错误),因为这可能会在执行确定值属于不同类型的代码后更改变量的类型,因此会在该代码中引入无法合理预期的错误。比如说

    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.
    
  • 更微妙的是,当区分字符串序列和非字符串序列时(因为字符串的定义特征是迭代它们也会产生字符串,而字符串本身是可写的),当扁平化结构时,代码可能会被破坏


    另一个答案提到了实现选项3的方法。虽然它可能会起作用,但它有上面提到的所有问题。这可能只适用于调试和开发

    利用列表等可变对象

    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
    

    嗯,
    y
    z
    的内容不会改变,因为它们指的是前面提到的
    x
    。。唯一改变的是
    x
    所指的内容。(如果我错了,请纠正我,因为我不知道C)。如果您只想更改名称
    x
    所指的内容,那么
    x=您所要的就是它。如果你想用一个新对象神奇地替换
    x
    所指的对象,那么这个对象必须在使用旧对象的任何地方都可见,包括dicts和tuples。@Schoolboy但这正是OP所要求的:不仅要替换
    x
    ,还要替换引用同一对象的所有其他名称。如果您没有意识到,在Python中
    1
    是一个对象,在主Python实现中,所有使用值
    1
    的东西都只是引用同一个对象。我应该补充一点,旧对象和新对象都有完全相同的接口,并且它们都是可变的(但它们在内部完全不同)。我可能会在所有列表和存储的属性中手动替换它们,或者创建一个代理对象(可能是最明智的事情,也是我应该做的事情)。但是我很好奇我是否可以偷偷地替换这个对象。@Marcin:Pyjack的
    replace\u all\u refs
    是最好的选择。它在字符串上不能可靠地工作,我怀疑它在任何未经GC跟踪的情况下都能工作。如果它在存在任意C扩展的情况下是可靠的,我会大吃一惊。那么,您想更改
    a
    存储位置中存储的数据吗?午饭后我会发布答案。@Schoolboy是的。基本上我把一个简单的对象放在了a中,当需要的时候,我想(懒洋洋地)把它升级到一个更复杂的对象b中。a和b有相同的接口,所以使用它们的代码应该能够处理这个问题。你应该在你的文章中包含更多关于你链接到什么的信息。