невозможно вызвать __add__ через __getattr __ (__getattribute__) - PullRequest
2 голосов
/ 05 марта 2010

Это объект класса A, в классе контейнера tmpA.Не все методы из A находятся в TMPA.Так, например: A + B присутствует, tmpA + B нет.Я пытаюсь вызвать метод из A для TMPA.Я могу вызвать простой метод, такой как change (), но __add__ - не работает.Если убрать наследование с объекта, код работает.


#--------------------------------------
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
#-------------------------------------
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'"

Ответы [ 3 ]

5 голосов
/ 05 марта 2010

Специальные методы ищутся в классе , то есть не в экземпляре класса (за исключением некоторых нарушений в классах старого стиля), что просто означает огромную головную боль).Так, в частности, класс __getattr__ (для нормальных классов в новом стиле) не вызывается для поиска __add__ при выполнении + - метакласса (type)здесь) __getattr__ is.

«Удаление наследования из object» означает возвращение обратно в мир hellzapoppin классов старого стиля и только накапливает боль на будущее: не !Скорее, если у вас есть класс, который должен делегировать некоторые специальные методы, кодируйте их явно в классе (напрямую или через декоратор класса) или создайте пользовательский метакласс, который знает об этой причуде (метакласс __getattr__ или другие средства,затем может выполнить задачу, которую вы жаждете).

2 голосов
/ 05 марта 2010

Я думаю, что X + Y принимается за X.__add__(Y).

Так что, если вы используете

class tempA(A), тогда temp_a + b работает, потому что наследует __add__ метод и использует его как temp_a.__add__(b).

, но если вы используете

class tempA(object), тогда у него нет __add__ метода в class tempA для вызовакогда он встречает temp_a + b.

1 голос
/ 05 марта 2010

Когда вы говорите tmp_a + b, Python ищет в tmp_a.__class__.__dict__, а затем object.__dict__ метод __add__ (в обход поиска типа hasattr / getattr)

Поскольку он нигде не найден, Python проверяет, есть ли у b метод __radd__, который может обрабатывать tmp_a в качестве другого параметра. Так как это не может, исключение выдается.

Вам нужно добавить несколько специальных методов в tmpA, чтобы заставить их работать должным образом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...