On 14/08/12 07:16, eryksun wrote:
On Mon, Aug 13, 2012 at 3:13 PM, Gregory, Matthew
<[email protected]> wrote:
I'm trying to create a new instance from an existing instance
def new_with_overrides(s1, **kwargs):
new_params = {'a': s1.a, 'b': s1.b}
for (k, v) in kwargs.iteritems():
if k in new_params:
new_params[k] = v
return Spam(new_params['a'], new_params['b'])
This works but it doesn't seem very extendable if new attributes are added to
Spam.
In general instance attributes won't map to __init__ arguments. You
can create a new instance by calling __new__. Then update from the
old dict and add in override attributes.
def new_with_overrides(obj1, **kwds):
obj2 = obj1.__new__(obj1.__class__)
obj2.__dict__.update(obj1.__dict__)
for k, v in kwds.items():
if k in obj2.__dict__:
obj2.__dict__[k] = v
return obj2
In general, this can fail too. The instance may have __slots__, it
may not have a __dict__ at all, it may be using properties or
__getattr__ etc. to implement computed attributes. All sorts of things
can go wrong when copying arbitrary instances. That's why there is an
entire protocol so that types can make themselves copyable.
Matt, if you're trying to make a "copy any instance" utility function, you
are re-inventing the wheel. See the copy module instead.
If you're looking to make an short-cut for your own class, my recommendation
is that you give your class two methods:
# Your class MUST inherit from object or some other builtin for this to work
class MyClass(object):
def to_mapping(self):
"""Return a dict of whatever arguments created the instance."""
return {"a": self.a, ...}
@classmethod
def from_mapping(cls, adict, **kwargs):
d = dict(adict, **kwargs)
return cls(**d)
Typical usage:
x = MyClass(a=1, b=2, c=3)
y = x.from_mapping(x.to_mapping(), a=999)
--
Steven
_______________________________________________
Tutor maillist - [email protected]
To unsubscribe or change subscription options:
http://mail.python.org/mailman/listinfo/tutor