Как узнать, есть ли функция, определенная для экземпляра класса в Python? - PullRequest
0 голосов
/ 18 января 2010

Я хочу знать, определена ли функция для экземпляра класса

class c(object):
  def func(self): pass
cc = c()

>>> is_function_defined_for_instance(cc,'func')
True
>>> is_function_defined_for_instance(cc,'cnuf')
False

мои самые чистые попытки использовать функцию:

def is_function_defined_for_instance(instance,function):
  return callable(getattr(instance,function,None))

# returns True iff function is defined for class of instance (not super classes)
def is_function_defined_for_instance(instance,function):
  return bool(instance.__class__.__dict__.get(function))

есть ли встроенный или лучший способ добиться того, что я ищу?

Ответы [ 3 ]

3 голосов
/ 18 января 2010

В Python 2.6 или выше, рекомендуемый подход:

import collections

def is_func(instance, func):
  return isinstance(getattr(instance, func, None), collections.Callable)

Новые ABC (абстрактные базовые классы) в модуле collections являются правильным способом, в Python 2.6+ и 3.any, для выполнения такого рода «проверок типа утилитарной типизации» - гораздо более элегантных , несформированные и перспективные, чем более старые подходы, такие как callable встроенный, operator.isCallable, или проверка на наличие специальных специальных методов, таких как __call__. Поскольку isinstance теперь может быть перегружен, оставьте его на ABC, чтобы перегрузить его и выполнить проверки, заключив в капсулу любые подходы более низкого уровня, которые работают лучше всего!

Элегантность и преимущества нового подхода таковы, что, если вам нужно сделать свой код переносимым между старыми и новыми версиями Python, я рекомендую инкапсулировать «тесты на утку», которые вам требуются, в модуле, который может определить его функция зависит от sys.version - использование isinstance(x, collections.Y) в версии 2.6 или лучше, и более старых подходов, таких как hasattr(x, '__somespecialmethod__') или callable(x) в версии 2.5 или хуже.

Самое главное, и в более общем плане, не не загрязняет ваш новый основной код приложения старыми, низшими способами - если требования обратной переносимости вынуждают вашу общую систему иметь некоторый «мусор» ( чтобы продолжать работать на старых версиях Python), по крайней мере, прилично спрятать этот мусор в его собственном «отсеке» (где однажды вы сможете легко смести его, если позволяют ограничения развертывания вашего приложения! -).

2 голосов
/ 18 января 2010
>>> def is_func(instance, func):
    test = getattr(instance, func, None)
    if test and hasattr(test, '__call__'):
        return True

>>> is_func('', 'len')
>>> is_func({}, 'fromkeys')
True

или вы можете использовать inspect модуль:

>>> import inspect
>>> test = getattr(cc, 'func', None)
>>> inspect.ismethod(test)
True
0 голосов
/ 18 января 2010

Можете ли вы выдать какое-то пользовательское исключение, если метод отсутствует? (Я приезжаю с земли Руби здесь :))

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