Итак, вы хотите знать, как привязать уже связанный метод к другому экземпляру, используя только связанный метод и другой экземпляр. Это можно сделать так:
def some_python_kungfu(meth, obj):
return type(meth)(meth.__func__, obj, obj.__class__)
Атрибут __func__
действительно совпадает с с Недом Батчелдерсом im_func
, но __func__
совместим с Python 3.
В одном случае это не сработает: методы встроенных классов. Атрибуты __func__
и im_func
доступны только для пользовательских классов. Следовательно, это не удастся:
a = "that's no ordinary rabbit"
b = "consult the book of armaments"
b_split = some_python_kungfu(a.split, b)
Небольшая модификация решения Неда будет работать как со встроенными, так и с пользовательскими классами:
def some_python_kungfu(meth, obj):
return getattr(obj, meth.__name__)
Так будет ли это работать всегда? Ну ... нет, но камень преткновения довольно неясная и (я думаю) редко встречающаяся проблема: если имя метода (meth.__name__
) не совпадает с именем в словаре классов ('b'
) ), то getattr
либо вернет неправильный атрибут, либо выдаст AttributeError
. Например:
def external(self):
pass
class A(object):
b = external
Здесь A.b.__name__ == 'external'
вместо 'b'
, поэтому вместо getattr(obj, 'b')
будет вызываться getattr(obj, 'external')
.
Хотя оба предыдущих подхода имеют проблемы: один со встроенными классами и один с соединенными классами , обе проблемы не возникают одновременно ни при каких обстоятельствах. Поэтому комбинация будет работать во всех случаях:
def some_python_kungfu(meth, obj):
try:
return type(meth)(meth.__func__, obj, obj.__class__)
except AttributeError:
# meth is a built-in method, so meth.__name__ is always correct
return getattr(obj, meth.__name__)
Как объяснено в другом месте на этой странице, лучше всего было бы проигнорировать весь этот беспорядок и сделать это более чистым способом, например, используя методы unbound и передавая первый аргумент (self
) вручную, как в ответе Cixates. Но кто знает, это может оказаться полезным для некоторых из вас когда-нибудь, возможно, в несколько странных обстоятельствах. ;)