Я пишу декораторы, и часть того, что мне нужно сделать, - это определить, является ли функция функцией или методом. Есть ли способ узнать, к какому классу относится данный метод?
например Если бы я запустил этот код, что я мог бы написать в getOwner, чтобы заставить exampleFunc печатать что-то вроде <class '__main__'.Example>?
class Example:
def method(self):
print("I'm a method")
def exampleFunc(func):
owner = getOwner(func)
print(owner)
test = Example()
exampleFunc(test.method)
@coldspeed, независимо от конкретной терминологии, могу ли я найти класс, частью которого является эта функция?
Независимо от терминологии, функции не принадлежат классам, а функции не понимают и не отслеживают какую-либо информацию о своих классах, поэтому нет.
Лучше всего было бы перебрать каждый класс в вашей области и посмотреть, соответствует ли какой-либо из его методов методу, который была передана вашей функции.
@coldspeed, который будет работать в некоторых случаях, но что, если бы мне передали метод __call__?
Проверьте значение id, и оно все равно должно работать.
Например, Example.method in Example.__dict__.values() вернет True.
@coldspeed дайте ответ, и я приму его, это отлично работает





Если все, что вам нужно сделать, это выяснить, что ведет себя как функция - это метод или функция, это одна из целей модуля types.
import types
def is_method(f):
return type(f) == types.MethodType
В случае, если функционально-подобный объект является методом, вы можете найти его родительский класс следующим образом.
Обновлять Исправлен для совместимости с Python3.
def method_parent(f):
return f.__self__
Это не отвечает на вопрос.
@coldspeed «Я пишу декораторы, и часть того, что мне нужно сделать, - это определить, является ли функция функцией или методом».
"что я мог написать в getOwner, чтобы exampleFunc напечатал что-то вроде <class 'основной'.Example>?"
Я раньше не видел этот f.im_self. Можете ли вы предоставить какие-либо подтверждающие претензии или документацию по этому поводу?
Это не сработает, если вы разместили это здесь. Кроме того, я не вижу эквивалента python3.x.
@coldspeed Вместо этого вы можете использовать функцию getmembers(). И я придерживаюсь разумной интерпретации вопроса OP, что он хочет знать, как определить, является ли что-то методом - другой язык в вопросе, предлагающий его собственные попытки и мысли по решению проблемы.
Позвольте нам продолжить обсуждение в чате.
type(Example.method) возвращает «функцию» на python3. Вы уверены, что ваш первый метод тоже работает?
Если вы используете type(Example.method), у вас нет экземпляра, к которому мог бы быть привязан метод, и на самом деле это функция. Попробуйте type(Example().method). Это отлично работает в Python2 и Python3.
if isintance(f, types.MethodType): return f.__self__.__class__ не гарантирует, что это определяющий класс ... но позволит вам заставить mro выполнять поиск в дереве.
@AChampion Это мысль. Как вы думаете, предполагаемое приложение использует экземпляры или классы?
@HansMusgrave OP использует экземпляр.
Если у вас есть ссылка на классы, определенные в вашей области видимости, вам нужно будет проверить каждый из них:
def exampleFunc(f):
class_list = [...]
return any(f in vars(c).values() for c in class_List)
Это вернет True, если функция f является методом экземпляра. Однако, если вы хотите вернуть фактическое имя класса:
def exampleFunc(f):
class_list = [...]
for c in class_list:
if f in vars(c).values():
return c.__name__
return 'global function' if 'lambda' not in f.__name__ else 'lambda'
Обратите внимание, что это не работает для методов __dunder__ и методов, наследуемых вашим классом. Например,
class A:
def f1(self): pass
class B(A):
def f2(self): pass
print(vars(B))
mappingproxy({'__doc__': None,
'__module__': '__main__',
'f2': <function __main__.B.f2>})
Обратите внимание, что f1 не является частью Bmappingproxy.
+1 за использование dunder и за ваш подход. Вот ссылка на сайт, откуда происходит слово dunder.
Функции не «принадлежат» классам, поэтому в этом вопросе есть некорректная посылка.