Как определить, является ли переменная Python функцией?

689

У меня есть переменная, xи я хочу знать, указывает ли она на функцию или нет.

Я надеялся, что смогу сделать что-то вроде:

>>> isinstance(x, function)

Но это дает мне:

Traceback (most recent call last):
  File "<stdin>", line 1, in ?
NameError: name 'function' is not defined

Я выбрал это потому, что

>>> type(x)
<type 'function'>
Даниэль Н
источник
37
Я подавлен количеством ответов, решающих проблему путем поиска какого- либо атрибута вызова или вызываемой функции ... Чистый способ - это тип (a) == types.functionType, предложенный @ryan
AsTeR
44
@AsTeR Правильный способ проверить свойства объектов типа "утка" - это спросить их, крякают ли они, а не посмотреть, помещаются ли они в контейнер размером с утку. Подход «сравните это напрямую» даст неправильный ответ для многих функций, таких как встроенные функции.
Джон Феминелла
3
@JohnFeminella Хотя я с тобой согласен в принципе. ОП не спрашивал, был ли он вызван, просто если это функция. Возможно, можно утверждать, что ему нужно различие между, например, функциями и классами?
Маккей,
3
Для моих целей я пришел сюда, потому что хотел использовать insepct.getsourceразличные объекты, и на самом деле это имеет значение не для того, был ли объект вызван, а для того, чтобы это было чем-то, для чего выполнялась бы «функция» type(obj). Так как Google привел меня сюда, я бы сказал, что комментарий AsTeR был самым полезным ответом (для меня). Есть много других мест в Интернете для людей, чтобы открыть __call__или callable.
Церберталан
4
@AsTeR Это types.FunctionType, с большой буквы F.
Бен Марес

Ответы:

894

Если это для Python 2.x или для Python 3.2+, вы также можете использовать callable(). Раньше он устарел, но теперь не устарел, поэтому вы можете использовать его снова. Вы можете прочитать обсуждение здесь: http://bugs.python.org/issue10518 . Вы можете сделать это с:

callable(obj)

Если это для Python 3.x, но до 3.2, проверьте, есть ли у объекта __call__атрибут. Вы можете сделать это с:

hasattr(obj, '__call__')

Часто предлагаемый types.FunctionTypesподход не верен, потому что он не охватывает многие случаи, которые вы, вероятно, хотели бы, чтобы он прошел, как с buildins:

>>> isinstance(open, types.FunctionType)
False

>>> callable(open)
True

Правильный способ проверить свойства объектов типа «утка» - это спросить их, если они крякают, а не посмотреть, помещаются ли они в контейнер размером с утку. Не используйте, types.FunctionTypeесли у вас нет четкого представления о функции.

Джон Феминелла
источник
73
Это также не скажет вам, если это функция - просто если она может быть вызвана.
Крис Б.
23
Зависит от приложения, имеет ли значение различие или нет; Я подозреваю, что вы правы, что это не относится к первоначальному вопросу, но это далеко не точно.
Крис Б.
5
К классам может быть прикреплена функция вызова . Так что это определенно не очень хороший способ различения. Метод Райана лучше.
Брайан Брюггеман
43
концепция «типизирования утки» делает это лучшим ответом, например, «какое это имеет значение, если это функция, если она ведет себя как единое целое?»
jcomeau_ictx
8
Существуют случаи, когда различие между вызываемым и функцией имеет решающее значение, например, при написании декоратора (см. Мой комментарий к ответу Райана).
Турион
267

Встроенные типы, которые не имеют конструкторов во встроенном пространстве имен (например, функции, генераторы, методы), находятся в typesмодуле. Вы можете использовать types.FunctionTypeв isinstanceзвонке:

In [1]: import types
In [2]: types.FunctionType
Out[2]: <type 'function'>
In [3]: def f(): pass
   ...:
In [4]: isinstance(f, types.FunctionType)
Out[4]: True
In [5]: isinstance(lambda x : None, types.FunctionType)
Out[5]: True

Обратите внимание, что здесь используется очень специфическое понятие «функция», которое обычно не то, что вам нужно. Например, он отклоняет zip(технически класс):

>>> type(zip), isinstance(zip, types.FunctionType)
(<class 'type'>, False)

open (встроенные функции имеют другой тип):

>>> type(open), isinstance(open, types.FunctionType)
(<class 'builtin_function_or_method'>, False)

и random.shuffle(технически метод скрытого random.Randomэкземпляра):

>>> type(random.shuffle), isinstance(random.shuffle, types.FunctionType)
(<class 'method'>, False)

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

Райан
источник
5
+1 отвечая на вопрос. Однако попытка угадать, является ли объект функцией - или даже если это какой-либо вызываемый объект - обычно является ошибкой. Без дополнительной информации от ОП, конечно, сложно отмахнуться от нее, но все же ...
bobince
47
На самом деле он возвращает False для встроенных функций, например, «open» для eg. Поэтому, чтобы быть конкретным, вам нужно использовать isinstance (f, (types.FunctionType, types.BuiltinFunctionType)). И, конечно, если вы строго хотите просто функции, а не вызываемые объекты или методы.
Лукаш Коржибски
5
@ ŁukaszKorzybski и быть более опасным ... вы также должны проверить на functools.partial: isinstance(f, (types.FunctionType, types.BuiltinFunctionType, functools.partial))или проверить f.funcв таком случае.
Эстани
3
@bobince, как насчет этого варианта использования: я хочу написать декоратор, @fooкоторый я могу использовать как @fooи как @foo(some_parameter). Затем он должен проверить, с чем он вызывается, например, функция для декорирования (первый случай) или параметр (второй случай, в котором он должен вернуть еще один декоратор).
Турион
types.BuiltinFunctionTypeэто также тип («нормальных») встроенных методов , которые вы, вероятно, не хотите разрешать, если не идете по callableмаршруту.
user2357112 поддерживает Monica
92

Начиная с Python 2.1 вы можете импортировать isfunctionиз inspectмодуля.

>>> from inspect import isfunction
>>> def f(): pass
>>> isfunction(f)
True
>>> isfunction(lambda x: x)
True
Paolo
источник
3
Хорошо, но, похоже, он возвращает False для встроенных функций, таких как openи hasattr.
Zecc
12
@Zecc isbuiltin для этого.
Паоло
13
Смотрите inspect.isfunctionстроку документации: «Верните true, если объект является пользовательской функцией».
Марк Микофски
4
Обратите внимание, что isfunction не распознает функции functool.partial.
Измаил
74

Принятый ответ был в то время, когда он был предложен, считался правильным. Как выясняется, нет никакой замены для callable(), который возвращается в Python 3.2: В частности, callable()проверяет tp_callполе объекта испытания. Нет простого эквивалента Python. Большинство из предложенных тестов верны в большинстве случаев:

>>> class Spam(object):
...     def __call__(self):
...         return 'OK'
>>> can_o_spam = Spam()


>>> can_o_spam()
'OK'
>>> callable(can_o_spam)
True
>>> hasattr(can_o_spam, '__call__')
True
>>> import collections
>>> isinstance(can_o_spam, collections.Callable)
True

Мы можем бросить гаечный ключ в это, удалив __call__из класса. И просто чтобы сделать вещи более захватывающими, добавьте фальшивку __call__к экземпляру!

>>> del Spam.__call__
>>> can_o_spam.__call__ = lambda *args: 'OK?'

Обратите внимание, что это действительно не вызывается:

>>> can_o_spam()
Traceback (most recent call last):
  ...
TypeError: 'Spam' object is not callable

callable() возвращает правильный результат:

>>> callable(can_o_spam)
False

Но hasattrэто не так :

>>> hasattr(can_o_spam, '__call__')
True

can_o_spamимеет ли этот атрибут в конце концов; это просто не используется при вызове экземпляра.

Еще более тонкий, isinstance()также получает это неправильно:

>>> isinstance(can_o_spam, collections.Callable)
True

Поскольку мы использовали эту проверку ранее, а затем удалили метод, abc.ABCMeta кешируем результат. Возможно, это ошибка в abc.ABCMeta. Тем не менее, на самом деле нет никакого возможного способа, которым он мог бы дать более точный результат, чем результат, чем при использовании callable()самого себя, поскольку typeobject->tp_call метод слота недоступен каким-либо другим способом.

Просто используйте callable()

SingleNegationElimination
источник
5
Удивительная иллюстрация подводных камней hasattr(o, '__call__')подхода и почему callable(), если таковые имеются, превосходят.
МестреЛион
39

Следующее должно возвращать логическое значение:

callable(x)
Нихил Челлия
источник
1
Это решает его проблему, но он все еще создает загадку: если x имеет встроенный класс 'function' во встроенном модуле , а help (x .__ class__) описывает «class function», почему «function», по-видимому, «не определена»?
Кен
1
«функция» не является ключевым словом или встроенным типом. Тип функций определен в модуле «types» как «types.FunctionType»
Крис Б.
19

callable(x) будет возвращать истину , если переданный объект может быть вызван в Python, но функция не существует в Python 3.0, и , собственно говоря , не будет различать:

class A(object):
    def __call__(self):
        return 'Foo'

def B():
    return 'Bar'

a = A()
b = B

print type(a), callable(a)
print type(b), callable(b)

Вы получите <class 'A'> Trueи в <type function> Trueкачестве вывода.

isinstanceотлично работает, чтобы определить, является ли что-то функцией (попробуйте isinstance(b, types.FunctionType)); если вам действительно интересно узнать, можно ли что-то вызвать, вы можете использовать hasattr(b, '__call__')или просто попробовать.

test_as_func = True
try:
    b()
except TypeError:
    test_as_func = False
except:
    pass

Это, конечно, не скажет вам, может ли он вызываться, но выбрасывает, TypeErrorкогда он выполняется, или вообще не вызывается. Это может не иметь значения для вас.

Крис Б.
источник
8
Назвать это плохой идеей. Что если у него есть побочные эффекты или что-то действительно происходит, но это занимает очень много времени?
asmeurer
@asmeurer - Зачем еще вам нужно знать, если это функция, если вы ее не вызываете?
детально
1
@detly: для отладки я регулярно хочу печатать все переменные в объекте, методы для меня обычно бесполезны, поэтому я не хочу их выполнять. В конце я просто перечисляю каждое неотзываемое свойство с соответствующими значениями :)
Wolph
2
То, что ты не звонишь, не означает, что это не звонят. Может быть, вы делаете отправку.
asmeurer
4
Существует большая проблема с использованием исключений, чтобы узнать, вызывается ли это или нет; что если он вызывается , но его вызов вызывает исключение, которое вы ищете? Вы оба молча проигнорируете ошибку и ошибочно определите , была ли она вызвана. Когда вы используете EAFP, вы действительно хотите избежать слишком большого количества попыток, но для этого варианта использования нет способа сделать это.
Бен
15

Если вы хотите обнаружить все, что синтаксически похоже на функцию: функцию, метод, встроенную функцию fun / meth, lambda ..., но исключить вызываемые объекты (объекты с __call__определенным методом), попробуйте следующее:

import types
isinstance(x, (types.FunctionType, types.BuiltinFunctionType, types.MethodType, types.BuiltinMethodType, types.UnboundMethodType))

Я сравнил это с кодом is*()проверок в inspectмодуле, и приведенное выше выражение гораздо более полно, особенно если ваша цель - отфильтровать какие-либо функции или обнаружить обычные свойства объекта.

Марчин Войнарски
источник
Спасибо, что указали мне на typesмодуль. Я тестировал make_stemmer()фабрику, которая иногда возвращала функцию, а иногда вызываемый Stemmerэкземпляр, и мне нужно было обнаружить разницу.
вар
7

Попробуйте использовать callable(x).

maxyfc
источник
6

Если вы узнали C++, вы должны быть знакомы с function objectили functorозначает любой объект, который может be called as if it is a function.

В C ++ an ordinary function- это объект функции, а также указатель на функцию; в более общем смысле - это объект класса, который определяет operator(). В C ++ 11 и выше, the lambda expressionэто functorтоже.

Сходство, в Python, functorsэто все callable. An ordinary functionможет быть вызвано, a lambda expressionможет быть вызвано, functional.partialможет быть вызвано, экземпляры class with a __call__() methodмогут быть вызваны.


Хорошо, вернемся к вопросу: I have a variable, x, and I want to know whether it is pointing to a function or not.

Если вы хотите судить о том, действует ли объект как функция, то предложенный callableметод @John Feminellaв порядке.

Если вы хотите judge whether a object is just an ordinary function or not(не экземпляр вызываемого класса или лямбда-выражение), то xtypes.XXXпредложенный @Ryanвариант является лучшим выбором.

Затем я делаю эксперимент с использованием этого кода:

#!/usr/bin/python3
# 2017.12.10 14:25:01 CST
# 2017.12.10 15:54:19 CST

import functools
import types
import pprint

Определите класс и обычную функцию.

class A():
    def __call__(self, a,b):
        print(a,b)
    def func1(self, a, b):
        print("[classfunction]:", a, b)
    @classmethod
    def func2(cls, a,b):
        print("[classmethod]:", a, b)
    @staticmethod
    def func3(a,b):
        print("[staticmethod]:", a, b)

def func(a,b):
    print("[function]", a,b)

Определим функторы:

#(1.1) built-in function
builtins_func = open
#(1.2) ordinary function
ordinary_func = func
#(1.3) lambda expression
lambda_func  = lambda a : func(a,4)
#(1.4) functools.partial
partial_func = functools.partial(func, b=4)

#(2.1) callable class instance
class_callable_instance = A()
#(2.2) ordinary class function
class_ordinary_func = A.func1
#(2.3) bound class method
class_bound_method = A.func2
#(2.4) static class method
class_static_func = A.func3

Определите список функторов и список типов:

## list of functors
xfuncs = [builtins_func, ordinary_func, lambda_func, partial_func, class_callable_instance, class_ordinary_func, class_bound_method, class_static_func]
## list of type
xtypes = [types.BuiltinFunctionType, types.FunctionType, types.MethodType, types.LambdaType, functools.partial]

Судите, является ли функтор вызываемым. Как видите, все они могут быть вызваны.

res = [callable(xfunc)  for xfunc in xfuncs]
print("functors callable:")
print(res)

"""
functors callable:
[True, True, True, True, True, True, True, True]
"""

Оцените тип функтора (types.XXX). Тогда типы функторов не все одинаковы.

res = [[isinstance(xfunc, xtype) for xtype in xtypes] for xfunc in xfuncs]

## output the result
print("functors' types")
for (row, xfunc) in zip(res, xfuncs):
    print(row, xfunc)

"""
functors' types
[True, False, False, False, False] <built-in function open>
[False, True, False, True, False] <function func at 0x7f1b5203e048>
[False, True, False, True, False] <function <lambda> at 0x7f1b5081fd08>
[False, False, False, False, True] functools.partial(<function func at 0x7f1b5203e048>, b=4)
[False, False, False, False, False] <__main__.A object at 0x7f1b50870cc0>
[False, True, False, True, False] <function A.func1 at 0x7f1b5081fb70>
[False, False, True, False, False] <bound method A.func2 of <class '__main__.A'>>
[False, True, False, True, False] <function A.func3 at 0x7f1b5081fc80>
"""

Я рисую таблицу типов вызываемых функторов, используя данные.

введите описание изображения здесь

Затем вы можете выбрать типы функторов, которые подходят.

такие как:

def func(a,b):
    print("[function]", a,b)

>>> callable(func)
True
>>> isinstance(func,  types.FunctionType)
True
>>> isinstance(func, (types.BuiltinFunctionType, types.FunctionType, functools.partial))
True
>>> 
>>> isinstance(func, (types.MethodType, functools.partial))
False
Kinght 金
источник
6

В качестве принятого ответа Джон Феминелла заявил, что:

Правильный способ проверить свойства объектов типа «утка» - это спросить их, если они крякают, а не посмотреть, помещаются ли они в контейнер размером с утку. Подход «сравните это напрямую» даст неправильный ответ для многих функций, таких как встроенные функции.

Несмотря на то, что есть две библиотеки, чтобы строго различать функции, я рисую исчерпывающую сопоставимую таблицу:

8.9. types - Создание динамических типов и имен для встроенных типов - Документация Python 3.7.0

30,13. осмотреть - осмотреть живые объекты - документация Python 3.7.0

#import inspect             #import types
['isabstract',
 'isasyncgen',              'AsyncGeneratorType',
 'isasyncgenfunction', 
 'isawaitable',
 'isbuiltin',               'BuiltinFunctionType',
                            'BuiltinMethodType',
 'isclass',
 'iscode',                  'CodeType',
 'iscoroutine',             'CoroutineType',
 'iscoroutinefunction',
 'isdatadescriptor',
 'isframe',                 'FrameType',
 'isfunction',              'FunctionType',
                            'LambdaType',
                            'MethodType',
 'isgenerator',             'GeneratorType',
 'isgeneratorfunction',
 'ismethod',
 'ismethoddescriptor',
 'ismodule',                'ModuleType',        
 'isroutine',            
 'istraceback',             'TracebackType'
                            'MappingProxyType',
]

«Утиная печать» является предпочтительным решением общего назначения:

def detect_function(obj):
    return hasattr(obj,"__call__")

In [26]: detect_function(detect_function)
Out[26]: True
In [27]: callable(detect_function)
Out[27]: True

Что касается встроенной функции

In [43]: callable(hasattr)
Out[43]: True

Когда нужно сделать еще один шаг, чтобы проверить, встроена ли функция или пользовательская функция

#check inspect.isfunction and type.FunctionType
In [46]: inspect.isfunction(detect_function)
Out[46]: True
In [47]: inspect.isfunction(hasattr)
Out[47]: False
In [48]: isinstance(detect_function, types.FunctionType)
Out[48]: True
In [49]: isinstance(getattr, types.FunctionType)
Out[49]: False
#so they both just applied to judge the user-definded

Определите, если builtin function

In [50]: isinstance(getattr, types.BuiltinFunctionType)
Out[50]: True
In [51]: isinstance(detect_function, types.BuiltinFunctionType)
Out[51]: False

Резюме

Наймите callableтипу утиной проверки функции,
используйте , types.BuiltinFunctionTypeесли вы дополнительно указаны требование.

Исчисление
источник
5

Функция - это просто класс с __call__методом, так что вы можете сделать

hasattr(obj, '__call__')

Например:

>>> hasattr(x, '__call__')
True

>>> x = 2
>>> hasattr(x, '__call__')
False

Это «лучший» способ сделать это, но в зависимости от того, почему вам нужно знать, может ли он быть вызван или записан, вы можете просто поместить его в блок try / execpt:

try:
    x()
except TypeError:
    print "was not callable"

Это спорно , если попробовать / за исключением более Python'y чем делать if hasattr(x, '__call__'): x().. Я хотел бы сказать , hasattrявляется более точным, так как вы не случайно поймать неправильный TypeError, например:

>>> def x():
...     raise TypeError
... 
>>> hasattr(x, '__call__')
True # Correct
>>> try:
...     x()
... except TypeError:
...     print "x was not callable"
... 
x was not callable # Wrong!
DBR
источник
Используйте обработку исключений только для защиты от непредвиденного поведения, а не для логического потока - это определенно не Pythonic.
получил
Ну, hasattr в основном делает getattr в блоке try / Кроме (хотя и в C). blog.jancewicz.net/2007/10/reflection-hasattr.html
DBR
@dbr: Но hasattr более эстетичен.
Nikhil Chelliah
5

Вот несколько других способов:

def isFunction1(f) :
    return type(f) == type(lambda x: x);

def isFunction2(f) :
    return 'function' in str(type(f));

Вот как я придумал второе:

>>> type(lambda x: x);
<type 'function'>
>>> str(type(lambda x: x));
"<type 'function'>"
# Look Maa, function! ... I ACTUALLY told my mom about this!
Сумух Барве
источник
Это мило! Должно работать на всех версиях python2.x и python3.x!
Саурав Кумар
4

Вместо проверки '__call__'(которая не является исключительными функции), вы можете проверить , есть ли определенный пользователь функции атрибуты func_name, func_docи т.д. Это не работает для методов.

>>> def x(): pass
... 
>>> hasattr(x, 'func_name')
True

Другой способ проверки - использование isfunction()метода из inspectмодуля.

>>> import inspect
>>> inspect.isfunction(x)
True

Чтобы проверить, является ли объект методом, используйте inspect.ismethod()

Стефан ван ден Аккер
источник
4

Так как у классов также есть __call__метод, я рекомендую другое решение:

class A(object):
    def __init__(self):
        pass
    def __call__(self):
        print 'I am a Class'

MyClass = A()

def foo():
    pass

print hasattr(foo.__class__, 'func_name') # Returns True
print hasattr(A.__class__, 'func_name')   # Returns False as expected

print hasattr(foo, '__call__') # Returns True
print hasattr(A, '__call__')   # (!) Returns True while it is not a function
guneysus
источник
1
Согласитесь с вашим ответом, ответ Джона Феминеллы hasattr(obj, '__call__')неоднозначен.
GoingMyWay
4

Обратите внимание, что классы Python также могут вызываться.

Чтобы получить функции (и под функциями мы подразумеваем стандартные функции и лямбды), используйте:

import types

def is_func(obj):
    return isinstance(obj, (types.FunctionType, types.LambdaType))


def f(x):
    return x


assert is_func(f)
assert is_func(lambda x: x)
Лукаш Рогальский
источник
2

Какая бы функция ни была классом, вы можете взять имя класса экземпляра x и сравнить:


if(x.__class__.__name__ == 'function'):
     print "it's a function"
Катсу
источник
2

Решения, использующие hasattr(obj, '__call__')и callable(.)упомянутые в некоторых ответах, имеют главный недостаток: оба возвращаются Trueдля классов и экземпляров классов с __call__()методом. Например.

>>> import collections
>>> Test = collections.namedtuple('Test', [])
>>> callable(Test)
True
>>> hasattr(Test, '__call__')
True

Один правильный способ проверки, является ли объект пользовательской функцией (и ничего кроме этого), заключается в использовании isfunction(.):

>>> import inspect
>>> inspect.isfunction(Test)
False
>>> def t(): pass
>>> inspect.isfunction(t)
True

Если вам нужно проверить другие типы, взгляните на осмотр - осмотр живых объектов .

Джеральд Сенаркленс де Гранси
источник
2

Точная проверка функций

вызываемое это очень хорошее решение. Однако я хотел относиться к этому противоположно Джону Феминелле. Вместо того, чтобы относиться к этому так:

Правильный способ проверить свойства объектов типа «утка» - это спросить их, если они крякают, а не посмотреть, помещаются ли они в контейнер размером с утку. Подход «сравните это напрямую» даст неправильный ответ для многих функций, таких как встроенные функции.

Мы будем относиться к этому так:

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

Как бы мы это реализовали?

Модуль 'types' имеет множество классов для обнаружения функций, наиболее полезными из которых являются types.FunctionType , но есть и множество других, таких как тип метода, встроенный тип и лямбда-тип. Мы также будем рассматривать объект functools.partial как функцию.

Простой способ проверить, является ли это функцией, заключается в использовании условия isinstance для всех этих типов. Ранее я хотел создать базовый класс, который наследует все вышеперечисленное, но я не могу этого сделать, так как Python не позволяет нам наследовать от некоторых из вышеперечисленных классов.

Вот таблица того, какие классы могут классифицировать, какие функции:

Таблица функций от kinght- 金 Над таблицей функций Kinght- 金

Код, который делает это

Теперь этот код выполняет всю работу, описанную выше.

from types import BuiltinFunctionType, BuiltinMethodType,  FunctionType, MethodType, LambdaType
from functools import partial

def is_function(obj):
  return isinstance(obj, (BuiltinFunctionType, BuiltinMethodType,  FunctionType, MethodType, LambdaType, partial))

#-------------------------------------------------

def my_func():
  pass

def add_both(x, y):
  return x + y

class a:
  def b(self):
    pass

check = [

is_function(lambda x: x + x),
is_function(my_func),
is_function(a.b),
is_function(partial),
is_function(partial(add_both, 2))

]

print(check)
>>> [True, True, True, False, True]

Один ложный был is_function (частичный), потому что это класс, а не функция, и это именно функции, а не классы. Вот предварительный просмотр для вас, чтобы попробовать код из.

Вывод

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

Наш пользовательский is_function (obj) , возможно, с некоторыми правками, является предпочтительным методом для проверки того, является ли объект функцией, если вы не учитываете экземпляр вызываемого класса как функцию, а только функции, определенные встроенными , или с помощью lambda , def или частично .

И я думаю, что это все завершает. Хорошего дня!

Корман
источник
1

В Python3 я придумал, type (f) == type (lambda x:x)что дает, Trueесли fявляется функцией, а Falseесли нет. Но я думаю, что я предпочитаю isinstance (f, types.FunctionType), который чувствует себя менее специальным. Я хотел сделать type (f) is function, но это не работает.

Аарон
источник
0

Следуя предыдущим ответам, я придумал это:

from pprint import pprint

def print_callables_of(obj):
    li = []
    for name in dir(obj):
        attr = getattr(obj, name)
        if hasattr(attr, '__call__'):
            li.append(name)
    pprint(li)
Джабба
источник
0

Вы можете попробовать это:

if obj.__class__.__name__ in ['function', 'builtin_function_or_method']:
    print('probably a function')

или даже что-то более странное

if "function" in lower(obj.__class__.__name__):
    print('probably a function')
tinnick
источник
-1

Если код будет продолжать выполнять вызов, если значение вызывается, просто выполните вызов и поймайте TypeError.

def myfunc(x):
  try:
    x()
  except TypeError:
    raise Exception("Not callable")
Роджер Даль
источник
4
Это опасно; Вы понятия не имеете, какие побочные эффекты xимеют.
cwallenpoole
-2

Ниже приведен «способ repr», чтобы проверить это. Также это работает с лямбдой.

def a():pass
type(a) #<class 'function'>
str(type(a))=="<class 'function'>" #True

b = lambda x:x*2
str(type(b))=="<class 'function'>" #True
Vova
источник
-3

Это работает для меня:

str(type(a))=="<class 'function'>"
Рафаэль Де Ача
источник
1
И что это говорит нам, если результатом является пустая строка? Для функции, я получаю "<type 'function'>", для целого числа, я получаю "<type 'int'>", поэтому я не понимаю, как это работает для вас: /
pawamoy
Теперь работает только для Python 3 :) Также, в зависимости от первоначальной цели вопроса, он будет неполным: следует openли считать встроенную функцию функцией? str(type(open))дает <class 'builtin_function_or_method'>в Python 3.
Pawamoy