Обнаружение связанного метода в классах (не экземплярах) в Python 3 - PullRequest
2 голосов
/ 07 декабря 2011

Учитывая класс C с функцией или методом f, я использую inspect.ismethod(obj.f) (где obj - это экземпляр C), чтобы узнать, является ли f связанным методом или нет.Есть ли способ сделать то же самое непосредственно на уровне класса (без создания объекта)?

inspect.ismethod не работает так:

class C(object):

    @staticmethod
    def st(x):
        pass

    def me(self):
        pass

obj = C()

приводит к этому (в Python 3):

>>> inspect.ismethod(C.st) 
False
>>> inspect.ismethod(C.me)
False
>>> inspect.ismethod(obj.st) 
False
>>> inspect.ismethod(obj.me)
True

Я думаю, мне нужно проверить, еслиФункция / метод является членом класса и не является статической, но я не смог сделать это легко.Я думаю, что это можно сделать, используя classify_class_attrs, как показано здесь Как бы вы определили, где определено каждое свойство и метод класса Python? , но я надеялся, что есть другой более прямой путь.

Ответы [ 3 ]

2 голосов
/ 05 января 2015

В Python 3 нет связанных методов, поэтому вы не можете их обнаружить. Все, что у вас есть, это обычные функции. Самое большее, вы можете увидеть, есть ли у них квалифицированное имя с точкой , указывающее, что они вложены , а их первый аргумент имеет имя self:

if '.' in method.__qualname__ and inspect.getargspec(method).args[0] == 'self':
    # regular method. *Probably*

Это, конечно, не работает полностью для статических методов и вложенных функций, которые имеют self в качестве первого аргумента, а также для обычных методов, которые не используют self в качестве первого аргумента (что противоречит соглашению) .

Для статических методов и методов класса вам нужно взглянуть на словарь классов :

>>> isinstance(vars(C)['st'], staticmethod)
True

Это потому, что C.__dict__['st'] является фактическим staticmethod экземпляром, до привязки к классу .

0 голосов
/ 12 февраля 2013

Поскольку inspect.ismethod возвращает True для связанных и несвязанных методов в Python 2.7 (т. Е. Не работает), я использую:

def is_bound_method(obj):
    return hasattr(obj, '__self__') and obj.__self__ is not None

Это также работает для методов классов, реализованных в CНапример, int:

>>> a = 1
>>> is_bound_method(a.__add__)
True
>>> is_bound_method(int.__add__)
False

Но это не очень полезно в этом случае, поскольку inspect.getargspec не работает для функций, реализованных в C.

is_bound_method работает без изменений в Python 3, ноPython 3, inspect.ismethod правильно различает связанные и несвязанные методы, поэтому в этом нет необходимости.

0 голосов
/ 07 декабря 2011

Не могли бы вы использовать inspect.isroutine(...)? Запуск с вашим классом C Я получаю:

>>> inspect.isroutine(C.st)
True
>>> inspect.isroutine(C.me)
True
>>> inspect.isroutine(obj.st)
True
>>> inspect.isroutine(obj.me)
True

Объединение результатов inspect.isroutine(...) с результатами inspect.ismethod(...) может позволить вам вывести то, что вам нужно знать.

Редактировать: Ответ dm03514 предполагает, что вы также можете попробовать inspect.isfunction():

>>> inspect.isfunction(obj.me)
False
>>> inspect.isfunction(obj.st)
True
>>> inspect.isfunction(C.st)
True
>>> inspect.isfunction(C.me)
False

Хотя, как указал Эрнан, результаты inspect.isfunction(...) меняются в питоне 3.

...