can't call __add__ through __getattr__( __getattribute__ )
It is object of the class A, in container's class tmpA. Not all method
from A are in the tmpA. So for example:
A + B is present , tmpA + B isn't present. I try to call method from A for tmpA. I
can to call simple method, such as change(), but __add__
- don't
work. If to remove inheritance from object, the code works.
#--------------------------------------
class A(object):
def __init__( self, x, y ):
self.x = x
self.y = y
pass
#-------
def __add__( self, arg ):
tmp1 = self.x + arg.x
tmp2 = self.y + arg.y
return tmpA( A( tmp1, tmp2 ) )
def change( self, x, y ):
self.x = x
self.y = y
pass
pass
#------------------------------------------
class tmpA( object ):
def __init__( self, theA ):
self.A = theA
pass
#-------
def _print ( self ):
print " x =", self.A.x
print " y =", self.A.y
pass
#-------
def __call__( self ):
return self.A
#-------
def __coerce__( self, *args ):
return None
#-------
def __getattr__( self, *args ):
name = args[ 0 ]
try:
attr = None
exec "attr = self.__call__().%s" % name
return attr
except :
raise AttributeError
#--------------------------------------
class B( object ):
def __init__( self, x, y):
self.x = x
self.y = y
pass
#---------------开发者_如何学C----------------------
a=A( 1,2 );
b=B( 3,4 );
tmp_a = a + b;
tmp_a.change( 0, 0 ) # very well
v = tmp_a + b #TypeError: "unsupported operand type(s) for +: 'tmpA' and 'B'"
Special methods are looked up on the class, that is, not on the instance of the class (except for some irregularities in old-style classes, which just mean a huge headache). So in particular the class's __getattr__
(for sane, new-style classes) is not getting called to look up __add__
when a +
is performed - the metaclass's (type
's, here) __getattr__
is.
"Removing inheritance from object
" means popping right back into the hellzapoppin world of old-style classes and only stores up pain for the future: don't! Rather, if you have a class that must delegate some special methods, code them explicitly in the class (directly or via a class decorator), or make a custom metaclass that knows about this quirk (the metaclass's __getattr__
, or other means, can then perform the task you crave).
I think X + Y
is taken as X.__add__(Y)
.
So if you use
class tempA(A)
then temp_a + b
works because it inherits __add__
method and uses it like temp_a.__add__(b)
.
but if you use
class tempA(object)
then it does not have __add__
method in class tempA
to call when it encounters temp_a + b
.
When you say tmp_a + b
, Python looks in tmp_a.__class__.__dict__
and then object.__dict__
for the __add__
method (bypassing the hasattr/getattr type lookup)
Since it is not found anywhere, Python then looks to see if b
has an __radd__
method that can handle tmp_a
as the other parameter. Since it can't, the exception is thrown.
You will have to add a bunch of special methods to tmpA to get those to work properly.
精彩评论