Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Replace one python object with another everywhere

How do I replace a python object everywhere with another object?

I have two classes, SimpleObject and FancyObject. I've created a SimpleObject, and have several references to it. Now I'd like to create a FancyObject, and make all those references point to the new object.

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

a = b is not what I want, it just changes what a points to. I read the following would work, but doesn't. I get an error "Attribute __dict__ is not writable":

a.__dict__ = b.__dict__

What I want is the equivalent of (pseudo-C):

*a = *b

I know this is hacky, but is there any way to accomplish this?

like image 363
jdm Avatar asked Jul 26 '13 08:07

jdm


3 Answers

You can put that object in global namespace of separate module and than monkey patch it when you need.

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

P.S. Rely on monkey patching is a symptom of bad design

like image 109
denz Avatar answered Oct 27 '22 00:10

denz


There's no way. It'd let you mutate immutable objects and cause all sorts of nastiness.

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?
like image 27
user2357112 supports Monica Avatar answered Oct 26 '22 23:10

user2357112 supports Monica


PyJack has a function replace_all_refs that replaces all references to an object in memory.

An example from the docs:

>>> 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'))

Calling 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'))
like image 39
user2682863 Avatar answered Oct 26 '22 23:10

user2682863