У меня есть переменная, x
и я хочу знать, указывает ли она на функцию или нет.
Я надеялся, что смогу сделать что-то вроде:
>>> isinstance(x, function)
Но это дает мне:
Traceback (most recent call last):
File "<stdin>", line 1, in ?
NameError: name 'function' is not defined
Я выбрал это потому, что
>>> type(x)
<type 'function'>
insepct.getsource
различные объекты, и на самом деле это имеет значение не для того, был ли объект вызван, а для того, чтобы это было чем-то, для чего выполнялась бы «функция»type(obj)
. Так как Google привел меня сюда, я бы сказал, что комментарий AsTeR был самым полезным ответом (для меня). Есть много других мест в Интернете для людей, чтобы открыть__call__
илиcallable
.Ответы:
Если это для Python 2.x или для Python 3.2+, вы также можете использовать
callable()
. Раньше он устарел, но теперь не устарел, поэтому вы можете использовать его снова. Вы можете прочитать обсуждение здесь: http://bugs.python.org/issue10518 . Вы можете сделать это с:Если это для Python 3.x, но до 3.2, проверьте, есть ли у объекта
__call__
атрибут. Вы можете сделать это с:Часто предлагаемый
types.FunctionTypes
подход не верен, потому что он не охватывает многие случаи, которые вы, вероятно, хотели бы, чтобы он прошел, как с buildins:Правильный способ проверить свойства объектов типа «утка» - это спросить их, если они крякают, а не посмотреть, помещаются ли они в контейнер размером с утку. Не используйте,
types.FunctionType
если у вас нет четкого представления о функции.источник
Встроенные типы, которые не имеют конструкторов во встроенном пространстве имен (например, функции, генераторы, методы), находятся в
types
модуле. Вы можете использоватьtypes.FunctionType
вisinstance
звонке:Обратите внимание, что здесь используется очень специфическое понятие «функция», которое обычно не то, что вам нужно. Например, он отклоняет
zip
(технически класс):open
(встроенные функции имеют другой тип):и
random.shuffle
(технически метод скрытогоrandom.Random
экземпляра):Если вы делаете что-то конкретное для
types.FunctionType
экземпляров, например, декомпилируете их байт-код или просматриваете переменные замыкания, используйтеtypes.FunctionType
, но если вам просто нужен объект, который можно вызывать как функцию, используйтеcallable
.источник
isinstance(f, (types.FunctionType, types.BuiltinFunctionType, functools.partial))
или проверитьf.func
в таком случае.@foo
который я могу использовать как@foo
и как@foo(some_parameter)
. Затем он должен проверить, с чем он вызывается, например, функция для декорирования (первый случай) или параметр (второй случай, в котором он должен вернуть еще один декоратор).types.BuiltinFunctionType
это также тип («нормальных») встроенных методов , которые вы, вероятно, не хотите разрешать, если не идете поcallable
маршруту.Начиная с Python 2.1 вы можете импортировать
isfunction
изinspect
модуля.источник
open
иhasattr
.inspect.isfunction
строку документации: «Верните true, если объект является пользовательской функцией».Принятый ответ был в то время, когда он был предложен, считался правильным. Как выясняется, нет никакой замены для
callable()
, который возвращается в Python 3.2: В частности,callable()
проверяетtp_call
поле объекта испытания. Нет простого эквивалента Python. Большинство из предложенных тестов верны в большинстве случаев:Мы можем бросить гаечный ключ в это, удалив
__call__
из класса. И просто чтобы сделать вещи более захватывающими, добавьте фальшивку__call__
к экземпляру!Обратите внимание, что это действительно не вызывается:
callable()
возвращает правильный результат:Но
hasattr
это не так :can_o_spam
имеет ли этот атрибут в конце концов; это просто не используется при вызове экземпляра.Еще более тонкий,
isinstance()
также получает это неправильно:Поскольку мы использовали эту проверку ранее, а затем удалили метод,
abc.ABCMeta
кешируем результат. Возможно, это ошибка вabc.ABCMeta
. Тем не менее, на самом деле нет никакого возможного способа, которым он мог бы дать более точный результат, чем результат, чем при использованииcallable()
самого себя, посколькуtypeobject->tp_call
метод слота недоступен каким-либо другим способом.Просто используйте
callable()
источник
hasattr(o, '__call__')
подхода и почемуcallable()
, если таковые имеются, превосходят.Следующее должно возвращать логическое значение:
источник
Инструмент Python 2to3 ( http://docs.python.org/dev/library/2to3.html ) предлагает:
Кажется, это был выбран вместо
hasattr(x, '__call__')
метода из-за http://bugs.python.org/issue7006 .источник
callable()
для py3.3: bugs.python.org/issue10518#msg122309callable(x)
будет возвращать истину , если переданный объект может быть вызван в Python, но функция не существует в Python 3.0, и , собственно говоря , не будет различать:Вы получите
<class 'A'> True
и в<type function> True
качестве вывода.isinstance
отлично работает, чтобы определить, является ли что-то функцией (попробуйтеisinstance(b, types.FunctionType)
); если вам действительно интересно узнать, можно ли что-то вызвать, вы можете использоватьhasattr(b, '__call__')
или просто попробовать.Это, конечно, не скажет вам, может ли он вызываться, но выбрасывает,
TypeError
когда он выполняется, или вообще не вызывается. Это может не иметь значения для вас.источник
Если вы хотите обнаружить все, что синтаксически похоже на функцию: функцию, метод, встроенную функцию fun / meth, lambda ..., но исключить вызываемые объекты (объекты с
__call__
определенным методом), попробуйте следующее:Я сравнил это с кодом
is*()
проверок вinspect
модуле, и приведенное выше выражение гораздо более полно, особенно если ваша цель - отфильтровать какие-либо функции или обнаружить обычные свойства объекта.источник
types
модуль. Я тестировалmake_stemmer()
фабрику, которая иногда возвращала функцию, а иногда вызываемыйStemmer
экземпляр, и мне нужно было обнаружить разницу.Попробуйте использовать
callable(x)
.источник
Если вы узнали
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.
Затем я делаю эксперимент с использованием этого кода:
Я рисую таблицу типов вызываемых функторов, используя данные.
такие как:
источник
В качестве принятого ответа Джон Феминелла заявил, что:
Несмотря на то, что есть две библиотеки, чтобы строго различать функции, я рисую исчерпывающую сопоставимую таблицу:
8.9. types - Создание динамических типов и имен для встроенных типов - Документация Python 3.7.0
30,13. осмотреть - осмотреть живые объекты - документация Python 3.7.0
«Утиная печать» является предпочтительным решением общего назначения:
Что касается встроенной функции
Когда нужно сделать еще один шаг, чтобы проверить, встроена ли функция или пользовательская функция
Определите, если
builtin function
Резюме
Наймите
callable
типу утиной проверки функции,используйте ,
types.BuiltinFunctionType
если вы дополнительно указаны требование.источник
Функция - это просто класс с
__call__
методом, так что вы можете сделатьНапример:
Это «лучший» способ сделать это, но в зависимости от того, почему вам нужно знать, может ли он быть вызван или записан, вы можете просто поместить его в блок try / execpt:
Это спорно , если попробовать / за исключением более Python'y чем делать
if hasattr(x, '__call__'): x()
.. Я хотел бы сказать ,hasattr
является более точным, так как вы не случайно поймать неправильный TypeError, например:источник
Вот несколько других способов:
Вот как я придумал второе:
источник
Вместо проверки
'__call__'
(которая не является исключительными функции), вы можете проверить , есть ли определенный пользователь функции атрибутыfunc_name
,func_doc
и т.д. Это не работает для методов.Другой способ проверки - использование
isfunction()
метода изinspect
модуля.Чтобы проверить, является ли объект методом, используйте
inspect.ismethod()
источник
Так как у классов также есть
__call__
метод, я рекомендую другое решение:источник
hasattr(obj, '__call__')
неоднозначен.Обратите внимание, что классы Python также могут вызываться.
Чтобы получить функции (и под функциями мы подразумеваем стандартные функции и лямбды), используйте:
источник
Какая бы функция ни была классом, вы можете взять имя класса экземпляра x и сравнить:
источник
Решения, использующие
hasattr(obj, '__call__')
иcallable(.)
упомянутые в некоторых ответах, имеют главный недостаток: оба возвращаютсяTrue
для классов и экземпляров классов с__call__()
методом. Например.Один правильный способ проверки, является ли объект пользовательской функцией (и ничего кроме этого), заключается в использовании
isfunction(.)
:Если вам нужно проверить другие типы, взгляните на осмотр - осмотр живых объектов .
источник
Точная проверка функций
вызываемое это очень хорошее решение. Однако я хотел относиться к этому противоположно Джону Феминелле. Вместо того, чтобы относиться к этому так:
Мы будем относиться к этому так:
Как бы мы это реализовали?
Модуль 'types' имеет множество классов для обнаружения функций, наиболее полезными из которых являются types.FunctionType , но есть и множество других, таких как тип метода, встроенный тип и лямбда-тип. Мы также будем рассматривать объект functools.partial как функцию.
Простой способ проверить, является ли это функцией, заключается в использовании условия isinstance для всех этих типов. Ранее я хотел создать базовый класс, который наследует все вышеперечисленное, но я не могу этого сделать, так как Python не позволяет нам наследовать от некоторых из вышеперечисленных классов.
Вот таблица того, какие классы могут классифицировать, какие функции:
Над таблицей функций Kinght- 金
Код, который делает это
Теперь этот код выполняет всю работу, описанную выше.
Один ложный был is_function (частичный), потому что это класс, а не функция, и это именно функции, а не классы. Вот предварительный просмотр для вас, чтобы попробовать код из.
Вывод
вызываемый (объект) является предпочтительным способом , чтобы проверить , если объект является функцией , если вы хотите пойти на утиной типизации над абсолютами .
Наш пользовательский is_function (obj) , возможно, с некоторыми правками, является предпочтительным методом для проверки того, является ли объект функцией, если вы не учитываете экземпляр вызываемого класса как функцию, а только функции, определенные встроенными , или с помощью lambda , def или частично .
И я думаю, что это все завершает. Хорошего дня!
источник
В Python3 я придумал,
type (f) == type (lambda x:x)
что дает,True
еслиf
является функцией, аFalse
если нет. Но я думаю, что я предпочитаюisinstance (f, types.FunctionType)
, который чувствует себя менее специальным. Я хотел сделатьtype (f) is function
, но это не работает.источник
Следуя предыдущим ответам, я придумал это:
источник
Вы можете попробовать это:
или даже что-то более странное
источник
Если код будет продолжать выполнять вызов, если значение вызывается, просто выполните вызов и поймайте
TypeError
.источник
x
имеют.Ниже приведен «способ repr», чтобы проверить это. Также это работает с лямбдой.
источник
Это работает для меня:
источник
"<type 'function'>"
, для целого числа, я получаю"<type 'int'>"
, поэтому я не понимаю, как это работает для вас: /open
ли считать встроенную функцию функцией?str(type(open))
дает<class 'builtin_function_or_method'>
в Python 3.