Функция python2 vs python3 для привязки метода

Уважаемые знатоки Python 3!

с python2 можно было бы сделать следующее (я знаю, что это немного сложно, но это не главное: p):

class A(object):
  def method(self, other):
    print self, other

class B(object): pass

B.method = types.MethodType(A().method, None, B)
B.method() # print both A and B instances

с python3 больше нет несвязанных методов, только функции. Если я хочу такого же поведения, похоже, мне нужно ввести собственный дескриптор, например:

class UnboundMethod:
    """unbound method wrapper necessary for python3 where we can't turn
    arbitrary object into a method (no more unbound method and only function
    are turned automatically to method when accessed through an instance)
    """
    def __init__(self, callable):
        self.callable = callable

    def __get__(self, instance, objtype):
        if instance is None:
            return self.callable
        return types.MethodType(self.callable, instance)

поэтому я могу сделать:

B.method = UnboundMethodType(A().method)
B.method() # print both A and B instances

Есть ли другой способ сделать это без написания такого дескриптора?

ТИА


person sthenault    schedule 29.08.2012    source источник
comment
Быстрый комментарий не по теме: нет необходимости наследовать объект в Py3. Это всегда делается неявно. Для проверки просто print(anyobject.__mro__) (= порядок разрешения метода)   -  person cfi    schedule 29.08.2012
comment
Я считаю, что это дублирование [stackoverflow.com/questions/10729909/. Однако этот вопрос, вероятно, легче найти. Кроме того, он более понятен (по крайней мере, для меня), поэтому я бы проголосовал за его сохранение...   -  person cfi    schedule 29.08.2012
comment
@cfi, правда о наследовании объектов, исправлен образец кода UnboundMethod. Также вы правы, это вопрос, аналогичный вопросу о привязке скомпилированной/встроенной функции (кстати, у которой нет удовлетворительного ответа)   -  person sthenault    schedule 29.08.2012
comment
Вам не хватает строки: B.method = types.MethodType(A().method, None, B); б=В(); b.method() # распечатать экземпляры A и B   -  person Sheena    schedule 18.09.2012


Ответы (2)


B.method = lambda o: A.method(o,A())

b = B()
b.method()

линия b.method() затем вызывает A.method(b,A()). Это означает, что A инициализируется каждый раз. Чтобы избежать этого:

a = A()
B.method = lambda o: A.method(o,a)

теперь каждый раз, когда вы вызываете b.method() для любого экземпляра B, один и тот же экземпляр A передается в качестве второго аргумента.

person Sheena    schedule 07.11.2012

Ну, ваш код тоже не работает в Python 2, но я понимаю, что вы пытаетесь сделать. И вы можете использовать лямбда, как в ответе Шины, или functools.partial.

>>> import types
>>> from functools import partial

>>> class A(object):
...   def method(self, other):
...     print self, other
... 
>>> class B(object): pass
... 
>>> B.method = partial(A().method, A())
>>> B().method()
<__main__.A object at 0x112f590> <__main__.A object at 0x1132190>
person Lennart Regebro    schedule 12.05.2015