Rebinding __setattr__

J

Jan Schilleman

Hi all,

I am trying to redefine __setattr__.

The base class is in a library (actually, it is
win32com.client.DispatchBaseClass) and I do not want to touch it. My problem
is exemplified below. To my surprise, __setattr__ and __str__ behave
differently; I can redefine __str__ and the inherited __str__ is still the
redefined one. But redefining __setattr__ on the base class does not get
inherited. In Base.__dict__ the __setattr__ is the one I expected, but it is
not called from B.

What is the problem? Is __setattr__ cached somewhere [and not updated?]?

class Base:

def __setattr__(self, attr, value):
print 'Base __setattr__'
self.__dict__[attr] = value

def __str__(self):
return "Base"

class A(Base): pass
class B(Base): pass

def __setattr__(self, attr, value):
print 'alternative __setattr__'
self.__dict__[attr] = value

def __str__(self):
return "Alternative"

a = A()
b = B()

for i in (1, 2):
print
print 'run', i
print

print Base.__dict__
print A.__dict__
print B.__dict__

print
print 'a:', a
a.a1 = 1

print 'b:', b
b.b1 = 1

setattr(Base, '__setattr__', __setattr__)
setattr(A, '__setattr__', __setattr__)
setattr(Base, '__str__', __str__)
setattr(A, '__str__', __str__)
 
M

Maric Michaud

Le Monday 15 September 2008 01:06:08 Jan Schilleman, vous avez écrit :
Hi all,

I am trying to redefine __setattr__.

The base class is in a library (actually, it is
win32com.client.DispatchBaseClass) and I do not want to touch it. My
problem is exemplified below. To my surprise, __setattr__ and __str__
behave differently; I can redefine __str__ and the inherited __str__ is
still the redefined one. But redefining __setattr__ on the base class does
not get inherited. In Base.__dict__ the __setattr__ is the one I expected,
but it is not called from B.

What is the problem? Is __setattr__ cached somewhere [and not updated?]?

Yes, it doesn't work with classic classes, but do with new-style ones, I don't
know if this an accepted behavior or not.
Can't you use new-style classes ?

...[2]: '2.5.2 (r252:60911, May 28 2008, 19:19:25) \n[GCC 4.2.4 (Debian
4.2.4-1)]'

def __setattr__(self, name, value) :
print "A", name
....:
....:
....:
A c
A c
[69]: A.__setattr__ = lambda s, n, v : sys.stdout.write("%s, %s, %s\n" %
(s, n, v))
<__main__.A instance at 0x2b3b41546290>, c, 1
A c




def __setattr__(self, name, value) :
print "A", name
....:
....:
....:
A c
A c
[76]: A.__setattr__ = lambda s, n, v : sys.stdout.write("%s, %s, %s\n" %
(s, n, v))
[77]:
[78]: A().c, B().c = 1, 2
<__main__.A object at 0x2b3b45dfa350>, c, 1
<__main__.B object at 0x2b3b45dfa350>, c, 2
 
J

Jan Schilleman

That still would require changing the source of the library ... And i'm not
sure if it would have side effects.

"Maric Michaud" <[email protected]> schreef in bericht
Le Monday 15 September 2008 01:06:08 Jan Schilleman, vous avez écrit :
Hi all,

I am trying to redefine __setattr__.

The base class is in a library (actually, it is
win32com.client.DispatchBaseClass) and I do not want to touch it. My
problem is exemplified below. To my surprise, __setattr__ and __str__
behave differently; I can redefine __str__ and the inherited __str__ is
still the redefined one. But redefining __setattr__ on the base class does
not get inherited. In Base.__dict__ the __setattr__ is the one I expected,
but it is not called from B.

What is the problem? Is __setattr__ cached somewhere [and not updated?]?

Yes, it doesn't work with classic classes, but do with new-style ones, I
don't
know if this an accepted behavior or not.
Can't you use new-style classes ?

....[2]: '2.5.2 (r252:60911, May 28 2008, 19:19:25) \n[GCC 4.2.4 (Debian
4.2.4-1)]'

def __setattr__(self, name, value) :
print "A", name
....:
....:
....:
A c
A c
[69]: A.__setattr__ = lambda s, n, v : sys.stdout.write("%s, %s, %s\n" %
(s, n, v))
<__main__.A instance at 0x2b3b41546290>, c, 1
A c




def __setattr__(self, name, value) :
print "A", name
....:
....:
....:
A c
A c
[76]: A.__setattr__ = lambda s, n, v : sys.stdout.write("%s, %s, %s\n" %
(s, n, v))
[77]:
[78]: A().c, B().c = 1, 2
<__main__.A object at 0x2b3b45dfa350>, c, 1
<__main__.B object at 0x2b3b45dfa350>, c, 2
 
A

alex23

That still would require changing the source of the library ... And i'm not
sure if it would have side effects.

I'm not on a Windows box so can't test this atm, but perhaps you could
make a proxy object?

class DispatchBaseProxy(object):
def __init__(self):
self.base = DispatchBaseClass()
def __setattr__(self, attr, value):
"insert extra functionality here"
setattr(self.base, attr, value)
def __getattr__(self, attr):
getattr(self.base, attr)
...etc...
 

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,756
Messages
2,569,540
Members
45,025
Latest member
KetoRushACVFitness

Latest Threads

Top