Overriding iadd for dictionary like objects
Jan Kaliszewski
zuo at chopin.edu.pl
Wed Aug 26 21:00:10 EDT 2009
27-08-2009 o 00:48:33 Robert Kern <robert.kern at gmail.com> wrote:
> On 2009-08-26 17:16 PM, RunThePun wrote:
>> I'd like to build a database wrapper using DictMixin and allow items
>> to be appended by my own code. The problem is += is always understood
>> as setitem and getitem plainly.
>>
>> d = MyDict()
>> d['a'] = 1
>>
>> # this is the problem code that's I'd like to override. It's always
>> setitem('a', getitem('a') + 3)
>> d['a'] += 3
>> # i wanted to do something like my own 'appenditem' function which for
>> example could be useful if getitem is an expensive operation which can
>> be avoided.
>>
>> I hope that was clear enough of a request, it's really late at night
>> here...
>
> I'm sorry, this is just part of the syntax of Python. You cannot
> override it.
Though
d['a'] = 3
is equivalent to:
d.__setitem__('a', 3)
The
d['a'] += 3
*is not* equivalent to:
d.__setitem__('a', d.__getitem__('a') + 3)
*but is* equivalent to:
d.__getitem__('a').__iadd__(3)
Then you can override __getitem__() of MyDict in such a way that it
returns prepared (wrapped) object with overriden __iadd__() as you
want to.
How could I now it:
1 import collections
2 import functools
3 import itertools
4
5
6 def verbose_func(func):
7 'Function decorator that makes a function "verbose"'
8
9 @functools.wraps(func, assigned=('__name__', '__doc__'))
10 def func_wrapper(*args, **kwargs):
11 iargs = (map(str, args))
12 ikwargs = ('{0}={1}'.format(key, value)
13 for key, value in kwargs.items())
14 func_args = ', '.join(itertools.chain(iargs, ikwargs))
15 print('{0}({1})'.format(func.__name__, func_args))
16 return func(*args, **kwargs)
17
18 return func_wrapper
19
20
21 def verbose_cls(base):
22 'Class decorator that makes callable attributes "verbose"'
23
24 quiet = ('__new__', '__repr__', '__str__')
25
26 def cls_wrapper(cls):
27 for name in vars(base):
28 attr = getattr(cls, name)
29 if isinstance(attr, collections.Callable) and name not in
quiet:
30 setattr(cls, name, verbose_func(attr))
31 return cls
32
33 return cls_wrapper
34
35
36 @verbose_cls(dict)
37 class VerboseDict(dict):
38 pass
39
40
41 @verbose_cls(int)
42 class MyInt(int):
43
44 @verbose_func
45 def __iadd__(self, other):
46 int.__add__(self, other) # can do something more interesting
47
48
49 if __name__ == '__main__':
50 d = VerboseDict()
51
52 print("d['a'] = 3")
53 d['a'] = MyInt(3)
54
55 print("d['a'] += 3")
56 d['a'] += MyInt(3)
*j
--
Jan Kaliszewski (zuo) <zuo at chopin.edu.pl>
More information about the Python-list
mailing list