problem with Descriptors

Steven W. Orr steveo at syslang.net
Mon May 31 20:51:02 EDT 2010


I just discovered descriptors but what I want to do isn't working right.

I hope this isn't too long. :-(

Here's what I have that works:

class C(object):
   def g(self):
     print "dir(g):",dir(self.g)

def f(self, ss):
   print "ss = ", ss

cc = C()

cc.ff = f.__get__(C,cc)
cc.ff('Round 3')

And when I run it, it prints out:

ss =  Round 3


That's the part that works. I'm trying to use the above construct to implement a 
new kind of dict().

The idea is that I want to create a dict that knows about certain values that 
can have dependencies on other values. If you change a value that is a 
dependency of another value within the dict, then the target value will 
automatically recompute itself. In the example below, the value of the key 
"range" is dependent on the value of the key "stop".

When I run the code, the function recalc_range seems to be successfully saved as 
a bound method. (The save happens in AddDep) But then when I try to invoke the 
saved bound method, it yells at me that the arg to __getitem__ is of the wrong type.

Does anyone see what I did wrong?

class BalancedDict(dict):
   def __init__( self, initval={}, depDesc=None ):
     dict.__init__(self)
     self.target = []
     self.deplist = []
     self.recalc_f = []
     self.addDep( depDesc )
     if isinstance(initval, dict):
       dict.update(self, initval)

   def __setitem__(self, key, value):             # setting a keyword
     dict.__setitem__(self, key, value)
     for ii, deps in enumerate(self.deplist):
       if key in deps:
	print '__setitem__:recalc_f[%d]'%ii,self.recalc_f[ii]
	print '__setitem__:targ:',self.target[ii]
	print '__setitem__:deplist:',self.deplist[ii]
	self.recalc_f[ii](self.target[ii],self.deplist[ii])

   def addDep(self, depDesc=None):
     if not depDesc:
       return
     for jj in depDesc:
       self.target.append(jj[0])
       self.deplist.append(jj[1])
       self.recalc_f.append(None)
       idx = len(self.recalc_f) - 1
       self.recalc_f[idx] = jj[2].__get__(BalancedDict, self)
       print 'addDep:self.recalc_f[%d]:'%idx, self.recalc_f[idx]


if __name__ == "__main__":
   import pprint

   def recalc_range(self, target, deplist):
     print 'recalc_range:type(self):', type(self), "self:",self
     print 'recalc_range:target:', target
     print 'recalc_range:deplist:', deplist
     stop = None
     for ii in deplist:
       if ii == 'stop':
	print "ii:",ii
	print "self:", self, type(self)
	stop = self.__getitem__(ii)
     if ( isinstance( stop, int ) ):
       self.__setitem__( self[target], range( stop ) )

   pp = pprint.PrettyPrinter()
   dd = BalancedDict()
   print 'dd: Init'
   pp.pprint(dd)
   dd.addDep([['range', ['stop'], recalc_range]])
   dd['stop'] = 40
   print 'dd: After start stop and step'
   pp.pprint(dd)

C:\Users\Steve\Documents\PythonSamples>python -i vfunc3.py
dd: Init
{}
addDep:self.recalc_f[0]: <bound method ?.recalc_range of <class 
'__main__.BalancedDict'>>
__setitem__:recalc_f[0] <bound method ?.recalc_range of <class
'__main__.BalancedDict'>>
__setitem__:targ: range
__setitem__:deplist: ['stop']
recalc_range:type(self): <type 'type'> self: <class '__main__.BalancedDict'>
recalc_range:target: range
recalc_range:deplist: ['stop']
ii: stop
self: <class '__main__.BalancedDict'> <type 'type'>
Traceback (most recent call last):
   File "vfunc3.py", line 55, in <module>
     dd['stop'] = 40
   File "vfunc3.py", line 20, in __setitem__
     self.recalc_f[ii](self.target[ii],self.deplist[ii])
   File "vfunc3.py", line 46, in recalc_range
     stop = self.__getitem__(ii)
TypeError: descriptor '__getitem__' requires a 'dict' object but received a 'str'
 >>>




-- 
Time flies like the wind. Fruit flies like a banana. Stranger things have  .0.
happened but none stranger than this. Does your driver's license say Organ ..0
Donor?Black holes are where God divided by zero. Listen to me! We are all- 000
individuals! What if this weren't a hypothetical question?
steveo at syslang.net



More information about the Python-list mailing list