problem with Descriptors

S

Steven W. Orr

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
 
P

Peter Otten

Steven said:
I just discovered descriptors but what I want to do isn't working right.
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?
self.recalc_f[idx] = jj[2].__get__(BalancedDict, self)

The __get__() method's signature is

__get__(self, obj, type=None)

not the other way round. But the real problem is that you are not heeding
Kernighan's warning that debugging is twice as hard as writing the code in
the first place...

Peter
 

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
473,769
Messages
2,569,582
Members
45,060
Latest member
BuyKetozenseACV

Latest Threads

Top