В Python вы можете вызвать метод экземпляра класса A, но передать экземпляр класса B? - PullRequest
6 голосов
/ 24 апреля 2009

В целях многократного использования существующего кода, который был определен как метод экземпляра другого класса, я пытался сделать что-то вроде следующего:

class Foo(object):
  def __init__(self):
    self.name = "Foo"

  def hello(self):
    print "Hello, I am " + self.name + "."

class Bar(object):
  def __init__(self):
    self.name = "Bar"


bar = Bar()
Foo.hello(bar)

но это приводит к:

TypeError: необязательный метод hello () должен вызываться с экземпляром Foo в качестве первого аргумента (вместо этого используется экземпляр Bar)

Возможно ли что-то подобное?


Мне должно было быть ясно, что я знаю, что это плохая идея. Очевидно, что реальное решение - это рефакторинг. Я просто подумал, что должен быть способ, и оказывается, что он есть.

Спасибо за комментарии.

Ответы [ 4 ]

9 голосов
/ 24 апреля 2009

Похоже, это работает:

Foo.hello.im_func(bar)

Привет, я Бар.

Я думаю, мне нужно прочитать это немного сложнее ...

5 голосов
/ 24 апреля 2009

Это происходит потому, что python оборачивает функции класса как «несвязанный метод», который выполняет эту проверку типа. Здесь есть некоторое описание решений, связанных с этим здесь .

Обратите внимание, что в Python 3 эта проверка типов фактически была отменена (см. Примечание в конце этой статьи), поэтому ваш подход будет работать там.

2 голосов
/ 29 декабря 2015

Это старый вопрос, но Python эволюционировал и, похоже, стоит на него указать:

в Python 3 больше нет <unbound method C.x>, поскольку несвязанный метод - это просто <function __main__.C.x>!

Что, вероятно, означает, что код в исходном вопросе не следует рассматривать / что / выкл. Во всяком случае, Python всегда занимался печатью уток, не так ли ?!

Refs:

Альтернативное решение в Py2

Обратите внимание, что существует также альтернативное решение "исследовательского" вопроса (см. Python: Bind a Unbound Method? ):

In [6]: a = A.a.im_func.__get__(B(), B)

In [7]: a
Out[7]: <bound method B.a of <__main__.B instance at 0x7f37d81a1ea8>>

In [8]: a(2)
2

Ref:

Некоторые примеры кода ipython

питон 2

In [1]: class A():
    def a(self, a=0):
        print a
   ...:

In [2]: A.a
Out[2]: <unbound method A.a>

In [3]: A.a.im_func
Out[3]: <function __main__.a>

In [4]: A.a(B())
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-4-7694121f3429> in <module>()
----> 1 A.a(B())

TypeError: unbound method a() must be called with A instance as first argument (got B instance instead)

питон 3

In [2]: class A():
    def a(self, a=0):
        print(a)
   ...:

In [3]: def a():
   ...:     pass
   ...:

In [4]: class B():
   ...:     pass

In [5]: A.a(B())
0

In [6]: A.a
Out[6]: <function __main__.A.a>
0 голосов
/ 24 апреля 2009

Некоторое время назад я размышлял о той же «функции» в Perl на PerlMonks, и общий консенсус заключался в том, что, пока он работает (как и в Python), вы не должны так поступать.

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