Я просмотрел эту тему, но некоторые концепции выше моего текущего уровня. В Python 2.x существует встроенный метод callable()
; есть ли простой способ проверить, можно ли что-то вызвать или не использовать Python 3?
альтернатива callable(), для использования в Python 3
comment
Я не согласен с вашим выбором принятого ответа. Я думаю, что ответ Джофоркера лучше.
- person Андрей Беньковский   schedule 25.01.2016
comment
Я согласен. Мой ответ устарел - было бы неплохо, если бы ОП изменил ответ на один из действующих на данный момент.
- person Chinmay Kanchi   schedule 03.02.2016
Ответы (3)
Вместо этого вы можете просто сделать hasattr(object_name, '__call__')
. В отличие от Python 2.x, это работает для всех вызываемых объектов, включая классы.
person
Chinmay Kanchi
schedule
08.12.2010
В Python 2.x это работает для классов нового стиля, но не для старых. Помните, однако, что
__call__
, вызываемый для класса (нового стиля), является type
(или метаклассом класса), а не классом.
- person kindall; 08.12.2010
@kindall: Хорошее замечание, о котором стоит помнить. Хотя, конечно, было бы довольно странно, если бы было иначе. Это также позволяет вам делать причудливые вещи, такие как
class_name()()
- person Chinmay Kanchi; 08.12.2010
Имейте в виду, что это даст ложное срабатывание в следующем крайнем случае:
class C(object): pass; c = C(); c.__call__ = lambda self: None
. Несмотря на то, что c
теперь имеет функцию атрибута call, c()
завершится ошибкой, даже если проверка hasattr
завершится успешно. Я не уверен, но я не могу исключить возможность ложноотрицательного углового случая, хотя, если это возможно, для его запуска, вероятно, потребуются объекты, реализованные в C-коде.
- person mtraceur; 01.02.2018
Оно вернулось. Python 3.2 имеет callable()
; больше нет необходимости использовать одну из менее удобных альтернатив.
person
joeforker
schedule
06.04.2012
callable()
вернулся в Python 3.2.
Если вам нужно использовать Python 3.1 (крайне маловероятно), то в дополнение к проверке на __call__
есть также следующие решения:
2to3 изменяет
callable(x)
наisinstance(x, collections.Callable)
шесть применений
any("__call__" in klass.__dict__ for klass in type(x).__mro__)
Т.е. проверяет наличие
__call__
в базовых классах. Это напоминает мне, что я должен спросить Бенджамина, почему. :)
И, наконец, вы можете, конечно, просто попробовать:
try:
x = x()
except TypeError:
pass
person
Lennart Regebro
schedule
08.12.2010
Отличная ссылка 2to3... это убедительный аргумент в пользу использования
collections.Callable
. Азбуки сейчас везде, кажется.
- person Russ; 03.11.2011
Блестящий. Но попробовать/кроме совета страшно.
- person Shekhar; 10.11.2011
@Shekhar: обработка исключений не страшна, если вы к ней привыкли.
- person Lennart Regebro; 12.11.2011
@LennartRegebro Речь шла о вызове, чтобы проверить, является ли рассматриваемый объект вызываемым или нет. Часть моего кода чувствительна к этому. На самом деле это было не о попытке/кроме. Надеюсь, мой комментарий теперь более понятен.
- person Shekhar; 13.11.2011
@Shekhar: Нет, на самом деле совсем наоборот. try/except не страшны, и они относятся к коду, который чувствителен к тому, является ли что-то вызываемым или нет. Попытка/исключение - это очень питонический способ справиться с этим.
- person Lennart Regebro; 14.11.2011
@LennartRegebro Дело не в попытке/кроме :). Речь идет о выполнении x, чтобы увидеть, является ли x вызываемым. попробуй: взорвать(), кроме: пройти
- person Shekhar; 14.11.2011
@LennartRegebro Извините, что слишком долго, но я не согласен. У меня есть несколько вызываемых объектов в моем коде (вызов с более чем несколькими строками кода, несколько вызовов базы данных и иногда изменение состояния объекта). Возможно, я не предпочитаю вызывать их, чтобы увидеть, можно ли их вызывать.
- person Shekhar; 14.11.2011
@Shekhar: Нет, может быть, я не совсем понимаю. Дело не в том, чтобы вызвать его, чтобы увидеть, можно ли его вызвать. Дело в том, что вы просто делаете все, что хотите, как если бы это можно было вызвать. Вам вообще не нужно проверять. Если вызов вызывает ошибку типа, вы делаете все, что делаете, если они не вызываются. Это известно как EAFP, в отличие от того, что вы делаете, что называется LBYL, который считается непитоновским. См. sayspy.blogspot.com/2008/12. /
- person Lennart Regebro; 14.11.2011
Это старый разговор, но я должен отметить: что произойдет, если
x
сам попытается что-то вызвать и не перехватит полученное исключение TypeError? Тогда вы не определили, что x
нельзя вызывать, а скорее что какая-то цепочка вызовов в x
выдала TypeError. Чуть другой, но другой.
- person twooster; 10.03.2012
Преимущество использования проверки
isinstance(x, collections.Callable)
заключается в том, что ABCMeta.__subclasscheck__
кэширует свои вызовы.
- person forivall; 21.03.2013
@LennartRegebro: я думаю, что EAFP хорош в целом, но не для этого конкретного случая. Если x является вызываемым, но вызываемая функция вызывает TypeError, то это будет ошибочно распознано как не вызываемое.
- person olivecoder; 28.10.2015