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

Discussion in 'Python' started by Robert Brewer, Jan 7, 2005.

  1. Steven Bethard wrote:
    > I'm playing around with a mapping type that uses setdefault
    > as suggested
    > in http://www.python.org/moin/Python3_2e0Suggestions. The
    > default value
    > for a missing key is either a simple value, or a value
    > generated from a
    > function. If it's generated from the function, it should be
    > generated
    > new each time so that, for example, if the default is an empty list,
    > d[1] and d[2] don't access the same list. This is why 'c.x is c.x'
    > should be False if I'm using the function.
    >
    > The best option I guess is to rewrite this with a
    > _getdefault() function instead of a property:
    >
    > But I was hoping to avoid having two separate attributes (self._value
    > and self._func) when only one should have a value at any given time.


    It seems to me like you were using the property as a glorified flag.
    Just use a flag.

    ftypes = ('BuiltinFunctionType', 'BuiltinMethodType',
    'FunctionType', 'GeneratorType', 'LambdaType',
    'MethodType', 'UnboundMethodType',)

    class D(dict):
    def __init__(self):
    self._default = None
    self._call_default = False
    def __getitem__(self, key):
    if not key in self:
    if self._call_default:
    self[key] = self._default()
    else:
    self[key] = self._default
    return dict.__getitem__(self, key)
    def setdefaultvalue(self, value):
    self._default = value
    self._call_default = isinstance(value, ftypes)

    ....or:

    def setdefaultvalue(self, value, call_callables=True):
    self._default = value
    self._call_default = callable(value) and call_callables


    Robert Brewer
    MIS
    Amor Ministries
    Robert Brewer, Jan 7, 2005
    #1
    1. Advertising

  2. Robert Brewer wrote:
    > Steven Bethard wrote:
    >
    >>I'm playing around with a mapping type that uses setdefault
    >>as suggested
    >>in http://www.python.org/moin/Python3_2e0Suggestions. The
    >>default value
    >>for a missing key is either a simple value, or a value
    >>generated from a
    >>function. If it's generated from the function, it should be
    >>generated
    >>new each time so that, for example, if the default is an empty list,
    >>d[1] and d[2] don't access the same list. This is why 'c.x is c.x'
    >>should be False if I'm using the function.
    >>
    >>The best option I guess is to rewrite this with a
    >>_getdefault() function instead of a property:
    >>
    >>But I was hoping to avoid having two separate attributes (self._value
    >>and self._func) when only one should have a value at any given time.

    >
    >
    > It seems to me like you were using the property as a glorified flag.
    > Just use a flag.
    >
    > ftypes = ('BuiltinFunctionType', 'BuiltinMethodType',
    > 'FunctionType', 'GeneratorType', 'LambdaType',
    > 'MethodType', 'UnboundMethodType',)
    >
    > class D(dict):
    > def __init__(self):
    > self._default = None
    > self._call_default = False
    > def __getitem__(self, key):
    > if not key in self:
    > if self._call_default:
    > self[key] = self._default()
    > else:
    > self[key] = self._default
    > return dict.__getitem__(self, key)
    > def setdefaultvalue(self, value):
    > self._default = value
    > self._call_default = isinstance(value, ftypes)
    >
    > ...or:
    >
    > def setdefaultvalue(self, value, call_callables=True):
    > self._default = value
    > self._call_default = callable(value) and call_callables


    Well, the right solution using a flag for the particular behavior I was
    looking for would have to look something like:

    class D(dict):
    def __init__(self):
    self._default = None
    self._call = False
    def __getitem__(self, key):
    if not key in self:
    if self._call:
    func, args, kwds = self._default
    self[key] = func(*args, **kwds)
    else:
    self[key] = self._default
    return dict.__getitem__(self, key)
    def setdefault(self, value, call=False, *args, **kwds):
    if call:
    self._default = value, args, kwds
    else:
    self._default = value
    self._call = call

    where I also accept *args and **kwds when the default value is to be
    called. It's certainly doable with a flag, but note that I have to
    check the flag every time in both __getitem__ and setdefault. It'd
    minimize redundancy a bit if I only had to check it in one place. Guess
    I could do something like:

    class D(dict):
    def __init__(self):
    self._default = None
    self._call_default = False
    def __getitem__(self, key):
    if not key in self:
    self[key] = self._default()
    return dict.__getitem__(self, key)
    def setdefault(self, value, call=False, *args, **kwds):
    if call:
    def caller():
    return value(*args, **kwds)
    else:
    def caller():
    return value
    self._default = caller

    Then I only have to test call when setdefault is called. Not sure I
    like this any better though...


    Steve

    P.S. The reason I had two functions, setdefaultvalue and
    setdefaultfunction has to do with argument parsing for
    setdefaultfunction. Note that

    def setdefault(self, value, call=False, *args, **kwds):
    ...

    means that you can't call functions with keyword arguments 'value' or
    'call'. That means I have to rewrite this function as something like

    def setdefault(*args, **kwds):
    self = args[0]
    value = args[1]
    call = ???
    ...

    The problem is, if 'call' is a keyword argument, I don't know whether it
    was intended as one of the function arguments or as an argument to
    setdefault.

    If setdefaultvalue and setdefaultfunction are two separate methods, I
    don't run into this problem.
    Steven Bethard, Jan 7, 2005
    #2
    1. Advertising

  3. Robert Brewer

    Nick Coghlan Guest

    Steven Bethard wrote:
    > where I also accept *args and **kwds when the default value is to be
    > called. It's certainly doable with a flag, but note that I have to
    > check the flag every time in both __getitem__ and setdefault.


    Alternatively, always use a function for the default value, and set _func to
    lambda: x when working by value :)

    Cheers,
    Nick.


    --
    Nick Coghlan | | Brisbane, Australia
    ---------------------------------------------------------------
    http://boredomandlaziness.skystorm.net
    Nick Coghlan, Jan 8, 2005
    #3
    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. Steven Bethard
    Replies:
    1
    Views:
    292
    Nick Coghlan
    Jan 8, 2005
  2. Gerry Sutton
    Replies:
    1
    Views:
    527
    Peter Otten
    Apr 16, 2005
  3. Andrew Jocelyn
    Replies:
    6
    Views:
    6,510
    Andrew Jocelyn
    Feb 8, 2009
  4. David Garamond
    Replies:
    5
    Views:
    225
    Ara.T.Howard
    Jun 8, 2004
  5. Leon Bogaert
    Replies:
    19
    Views:
    318
    Robert Klemme
    Mar 23, 2008
Loading...

Share This Page