Найти класс владельца метода в Python

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

например Если бы я запустил этот код, что я мог бы написать в 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)

Функции не «принадлежат» классам, поэтому в этом вопросе есть некорректная посылка.

cs95 28.05.2018 01:09

@coldspeed, независимо от конкретной терминологии, могу ли я найти класс, частью которого является эта функция?

user189728 28.05.2018 01:10

Независимо от терминологии, функции не принадлежат классам, а функции не понимают и не отслеживают какую-либо информацию о своих классах, поэтому нет.

cs95 28.05.2018 01:11

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

cs95 28.05.2018 01:12

@coldspeed, который будет работать в некоторых случаях, но что, если бы мне передали метод __call__?

user189728 28.05.2018 01:12

Проверьте значение id, и оно все равно должно работать.

cs95 28.05.2018 01:13

Например, Example.method in Example.__dict__.values() вернет True.

cs95 28.05.2018 01:14

@coldspeed дайте ответ, и я приму его, это отлично работает

user189728 28.05.2018 01:14
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
8
884
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Если все, что вам нужно сделать, это выяснить, что ведет себя как функция - это метод или функция, это одна из целей модуля types.

import types

def is_method(f):
    return type(f) == types.MethodType

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

Обновлять Исправлен для совместимости с Python3.

def method_parent(f):
    return f.__self__

Это не отвечает на вопрос.

cs95 28.05.2018 01:20

@coldspeed «Я пишу декораторы, и часть того, что мне нужно сделать, - это определить, является ли функция функцией или методом».

Hans Musgrave 28.05.2018 01:20

"что я мог написать в getOwner, чтобы exampleFunc напечатал что-то вроде <class 'основной'.Example>?"

cs95 28.05.2018 01:21

Я раньше не видел этот f.im_self. Можете ли вы предоставить какие-либо подтверждающие претензии или документацию по этому поводу?

cs95 28.05.2018 01:22

Это не сработает, если вы разместили это здесь. Кроме того, я не вижу эквивалента python3.x.

cs95 28.05.2018 01:27

@coldspeed Вместо этого вы можете использовать функцию getmembers(). И я придерживаюсь разумной интерпретации вопроса OP, что он хочет знать, как определить, является ли что-то методом - другой язык в вопросе, предлагающий его собственные попытки и мысли по решению проблемы.

Hans Musgrave 28.05.2018 01:27

Позвольте нам продолжить обсуждение в чате.

Hans Musgrave 28.05.2018 01:27
type(Example.method) возвращает «функцию» на python3. Вы уверены, что ваш первый метод тоже работает?
cs95 28.05.2018 01:29

Если вы используете type(Example.method), у вас нет экземпляра, к которому мог бы быть привязан метод, и на самом деле это функция. Попробуйте type(Example().method). Это отлично работает в Python2 и Python3.

Hans Musgrave 28.05.2018 01:35
if isintance(f, types.MethodType): return f.__self__.__class__ не гарантирует, что это определяющий класс ... но позволит вам заставить mro выполнять поиск в дереве.
AChampion 28.05.2018 01:48

@AChampion Это мысль. Как вы думаете, предполагаемое приложение использует экземпляры или классы?

Hans Musgrave 28.05.2018 01:50

@HansMusgrave OP использует экземпляр.

AChampion 28.05.2018 01:51
Ответ принят как подходящий

Если у вас есть ссылка на классы, определенные в вашей области видимости, вам нужно будет проверить каждый из них:

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.

Chiheb Nexus 28.05.2018 01:29

Другие вопросы по теме