attribute save restore

C

Carl K

Is there a more elegant way of coding this:

x=o.p # save .p
o.p=0
o.m()
o.p=x # restore .p

seems very push/pop to me - like there should be a way that doesn't need a var
(x) or the save/set lines should be done in one command.

(personally I think .m would better be implemented by passing in a parameter,
but that isn't my choice.)

Carl K
 
S

Steven Bethard

Carl said:
Is there a more elegant way of coding this:

x=o.p # save .p
o.p=0
o.m()
o.p=x # restore .p

seems very push/pop to me - like there should be a way that doesn't need
a var (x) or the save/set lines should be done in one command.

With the appropriate context manger, you could write this as::

with setting(o, 'p', 2):
o.m()

Here's the code::
... def setting(obj, name, value):
... old_value = getattr(obj, name)
... setattr(obj, name, value)
... try:
... yield obj
... finally:
... setattr(obj, name, old_value)
... ... def __init__(self, x):
... self.x = x
... def m(self):
... print self.x
... ... c.m()
...
2 1

Of course, that just wraps up the same push/pop behavior you're doing
into a context manager.
(personally I think .m would better be implemented by passing in a
parameter, but that isn't my choice.)

Yep, that's the right answer. You should complain to whoever created
this API.

STeVe
 
C

Carsten Haese

Is there a more elegant way of coding this:

x=o.p # save .p
o.p=0
o.m()
o.p=x # restore .p

In Python 2.5, you could leverage the new "with" statement with a
properly crafted context manager along these lines:

"""
from __future__ import with_statement

class TempAttrSetter(object):
def __init__(self, obj, **attrs):
self.obj = obj
self.attrs = attrs

def __enter__(self):
self.saved_attrs = {}
for attr, newval in self.attrs.iteritems():
self.saved_attrs[attr] = getattr(self.obj, attr)
setattr(self.obj, attr, newval)

def __exit__(self, *args):
for attr in self.saved_attrs.keys():
setattr(self.obj, attr, self.saved_attrs[attr])

class Bag(object): pass
b = Bag()
b.x = 1

print b.x # prints 1
with TempAttrSetter(b, x=3):
print b.x # prints 3
print b.x # prints 1
"""

-Carsten
 
C

Carl K

Steven said:
With the appropriate context manger, you could write this as::

with setting(o, 'p', 2):
o.m()

Here's the code::

... def setting(obj, name, value):
... old_value = getattr(obj, name)
... setattr(obj, name, value)
... try:
... yield obj
... finally:
... setattr(obj, name, old_value)
...
... def __init__(self, x):
... self.x = x
... def m(self):
... print self.x
...
... c.m()
...
2
1

Of course, that just wraps up the same push/pop behavior you're doing
into a context manager.

Thanks.

As I was eating lunch I came up with:

x,o.p = o.p,0

Which I am pretty sure is just bad :)
I need to cut back on the hot sauce.
Yep, that's the right answer. You should complain to whoever created
this API.

Will do. Something is buggy anyway, so as long as I am commenting...

Carl K
 
B

Bruno Desthuilliers

Carl K a écrit :
Is there a more elegant way of coding this:

x=o.p # save .p
o.p=0
o.m()
o.p=x # restore .p

seems very push/pop to me - like there should be a way that doesn't need
a var (x) or the save/set lines should be done in one command.

(personally I think .m would better be implemented by passing in a
parameter, but that isn't my choice.)

I was about to comment on this. It looks like o.m is wanting to take an
optional arg defaulting to o.p, and you should probably propose a patch
to the author.

My 2 cents
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,431
Messages
2,571,677
Members
48,796
Latest member
Greg L.

Latest Threads

Top