switching an instance variable between a property and a normal value

Discussion in 'Python' started by Steven Bethard, Jan 7, 2005.

  1. I'd like to be able to have an instance variable that can sometimes be
    accessed as a property, and sometimes as a regular value, e.g. something
    like:

    py> class C(object):
    .... def usevalue(self, x):
    .... self.x = x
    .... def usefunc(self, func, *args, **kwds):
    .... self._func, self._args, self._kwds = func, args, kwds
    .... self.x = C._x
    .... def _get(self):
    .... return self._func(*self._args, **self._kwds)
    .... _x = property(_get)
    ....
    py> c = C()
    py> c.usevalue(4)
    py> c.x
    4
    py> c.usefunc(list)
    py> c.x # I'd like this to print []
    <property object at 0x04166DA0>

    Of course, the code above doesn't do what I want because C._x is a
    property object, so the assignment to self.x in usefunc just adds
    another name for that property object. If I use self._x (or
    getattr(self, '_x'), etc.) then self._func only gets called that one time:

    py> class C(object):
    .... def usevalue(self, x):
    .... self.x = x
    .... def usefunc(self, func, *args, **kwds):
    .... self._func, self._args, self._kwds = func, args, kwds
    .... self.x = self._x
    .... def _get(self):
    .... return self._func(*self._args, **self._kwds)
    .... _x = property(_get)
    ....
    py> c = C()
    py> c.usefunc(list)
    py> c.x is c.x # I'd like this to be False
    True

    Is there any way to get the kind of behavior I'm looking for? That is,
    is there any way to make self.x use the property magic only some of the
    time?

    Steve

    P.S. Yes, I know I could make both access paths run through the
    property magic, with code that looks something like:

    py> class C(object):
    .... _undefined = object
    .... def __init__(self):
    .... self._value, self._func = C._undefined, C._undefined
    .... def usevalue(self, x):
    .... self._value = x
    .... self._func = C._undefined
    .... def usefunc(self, func, *args, **kwds):
    .... self._func, self._args, self._kwds = func, args, kwds
    .... self._value = C._undefined
    .... def _get(self):
    .... if self._value is not C._undefined:
    .... return self._value
    .... if self._func is not C._undefined:
    .... return self._func(*self._args, **self._kwds)
    .... raise AttributeError('x')
    .... x = property(_get)
    ....
    py> c = C()
    py> c.usevalue(4)
    py> c.x
    4
    py> c.usefunc(list)
    py> c.x is c.x
    False

    This code is kinda complicated though because I have to make sure that
    only one of self._func and self._value is defined at any given time.
     
    Steven Bethard, Jan 7, 2005
    #1
    1. Advertising

  2. Steven Bethard

    Nick Coghlan Guest

    Re: switching an instance variable between a property and a normalvalue

    Steven Bethard wrote:
    > I'd like to be able to have an instance variable that can sometimes be
    > accessed as a property, and sometimes as a regular value, e.g. something
    > like:


    If you want the behaviour to be switchable per-instance, you have to go the
    route of always running through the property machinery, since property() creates
    a descriptor on the class, not the instance.

    On the other hand, if you want to switch the behaviour of every instance, then
    making usevalue and usefunc class methods may give you some mileage.

    I'm rather curious about your use case, though. . .

    Here's a different way of using the property machinery, too:

    Py> class C(object):
    .... def __init__(self):
    .... self._use_val = None
    .... def useval(self, x):
    .... self._val = x
    .... self._use_val = True
    .... def usefunc(self, func, *args, **kwds):
    .... self._func, self._args, self._kwds = (func, args, kwds)
    .... def _get(self):
    .... use_val = self._use_val
    .... if use_val is None:
    .... raise AttributeError('x')
    .... if use_val:
    .... return self._val
    .... else:
    .... return self._func(*self._args, **self._kwds)
    .... x = property(_get)
    ....
    Py> c = C()
    Py> c.useval(4)
    Py> c.x
    4
    Py> c.usefunc(list)
    Py> c.x
    []

    --
    Nick Coghlan | | Brisbane, Australia
    ---------------------------------------------------------------
    http://boredomandlaziness.skystorm.net
     
    Nick Coghlan, Jan 8, 2005
    #2
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Robert Brewer
    Replies:
    2
    Views:
    298
    Nick Coghlan
    Jan 8, 2005
  2. dost
    Replies:
    2
    Views:
    361
    Mark P
    Apr 25, 2006
  3. sahpathi
    Replies:
    4
    Views:
    335
    sahpathi
    Jun 12, 2006
  4. Leon Bogaert
    Replies:
    19
    Views:
    347
    Robert Klemme
    Mar 23, 2008
  5. Walle Wallen
    Replies:
    3
    Views:
    97
    Walle Wallen
    Apr 28, 2010
Loading...

Share This Page