Callable: примеры (PYTHON)

Функция callable в Python - проверка объектов на возможность вызова
Раздел: Встроенные функции, Интроспекция
callable(object: object): bool

Функция callable в Python

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

Функция используется в ситуациях, когда требуется динамическая обработка объектов, которые потенциально могут быть функциями, методами, классами или экземплярами классов с определенным методом. Такая проверка полезна перед непосредственным вызовом, чтобы избежать ошибок времени выполнения.

Аргументы и возвращаемое значение

Функция принимает один обязательный аргумент.

  • object (обязательный): Любой объект Python, проверяемый на возможность вызова.

Функция возвращает логическое значение bool.

  • Возвращает True: Если объект может быть вызван. Это относится к встроенным и пользовательским функциям, методам, классам, объектам с методом __call__, лямбда-функциям, генераторам функций, а также некоторым встроенным типам, например, property и staticmethod.
  • Возвращает False: Если объект не может быть вызван. Например, числа, строки, списки, словари, экземпляры большинства классов без метода __call__.

Примеры использования callable

Пример проверки различных типов объектов.

Проверка встроенной функции:

print(callable(len))
True

Проверка числа:

print(callable(42))
False

Проверка строки:

print(callable('hello'))
False

Проверка пользовательской функции:

def my_func(): pass
print(callable(my_func))
True

Проверка лямбда-функции:

my_lambda = lambda x: x * 2
print(callable(my_lambda))
True

Проверка класса:

class MyClass: pass
print(callable(MyClass))
True

Проверка экземпляра класса с методом __call__:

class CallableClass:
    def __call__(self):
        return 'Called'

obj = CallableClass()
print(callable(obj))
True

Проверка экземпляра класса без метода __call__:

class NonCallableClass: pass
obj = NonCallableClass()
print(callable(obj))
False

Похожие подходы в Python

В Python существуют другие способы проверки возможности вызова объекта.

  • Проверка атрибута __call__: Можно использовать функцию hasattr() для проверки наличия атрибута __call__ у объекта. hasattr(obj, '__call__'). Результат часто совпадает с callable(), но этот способ считается более низкоуровневым.
  • Использование блока try/except: Прямой вызов объекта внутри блока try с перехватом исключения TypeError. Этот подход предпочтителен, когда конечной целью является вызов, а не просто проверка, поскольку он соответствует принципу 'проще просить прощения, чем разрешения'.

Функция callable() является наиболее явным и читаемым способом проверки, когда требуется только определить возможность вызова без его осуществления.

Аналоги в других языках программирования

PHP: Функция is_callable() выполняет схожую проверку. Она может принимать строки с именами функций.

// PHP
var_dump(is_callable('strlen')); // bool(true)
var_dump(is_callable(123));      // bool(false)

JavaScript: Проверка осуществляется через оператор typeof.

// JavaScript
console.log(typeof alert === 'function'); // true
console.log(typeof 123 === 'function');   // false

Java: Прямого аналога нет. Проверка осуществляется через рефлексию или проверку интерфейсов.

// Java (пример с функциональным интерфейсом)
Runnable r = () -> {};
System.out.println(r instanceof Runnable); // true

C#: Используется проверка типа на делегат или через MethodInfo.

// C#
Action action = () => Console.WriteLine();
Console.WriteLine(action is Delegate); // True

Go: Проверка типа через рефлексию в пакете reflect.

// Go
f := func() {}
v := reflect.ValueOf(f)
fmt.Println(v.Kind() == reflect.Func) // true

Kotlin: Используется оператор is для проверки функционального типа.

// Kotlin
val f: () -> Unit = {}
println(f is Function<*>) // true

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

Типичные ошибки

Путаница между проверкой возможности вызова и проверкой существования объекта с заданным именем.

# Ошибка: проверка необъявленного имени
print(callable(undeclared_name))
NameError: name 'undeclared_name' is not defined

Функция callable() не проверяет корректность аргументов будущего вызова.

def func_with_args(x):
    return x

# callable вернет True, даже если вызов без аргументов вызовет ошибку
print(callable(func_with_args))
func_with_args() # Ошибка возникнет здесь
True
TypeError: func_with_args() missing 1 required positional argument: 'x'

Некорректное понимание результата для классов. Классы являются вызываемыми, но их экземпляры - нет, если не определен метод __call__.

class MyClass:
    pass

print('Класс callable?', callable(MyClass))
obj = MyClass()
print('Экземпляр callable?', callable(obj))
Класс callable? True
Экземпляр callable? False

Изменения в работе функции

В Python 3.x функция callable() была временно удалена в версии 3.0 и возвращена в версии 3.2 из-за ее полезности. В последних версиях Python (3.10, 3.11) сама функция callable() не претерпела синтаксических изменений, но изменения в системе типов (например, добавление typing.Callable) предоставили дополнительные средства для аннотации вызываемых объектов.

Расширенные примеры

Использование callable() для динамического вызова объектов из списка.

Пример python
def greet():
    return 'Hello'

class Multiplier:
    def __init__(self, factor):
        self.factor = factor
    def __call__(self, value):
        return value * self.factor

objects = [123, greet, 'text', Multiplier(5), lambda x: x**2]

for obj in objects:
    if callable(obj):
        # Для простоты, вызываем с аргументом 10, если принимает
        try:
            # Пытаемся вызвать с одним аргументом
            result = obj(10)
            print(f'Вызов {obj.__name__ if hasattr(obj, '__name__') else obj}: {result}')
        except TypeError:
            # Если не принимает аргументы, вызываем без них
            result = obj()
            print(f'Вызов {obj.__name__}: {result}')
    else:
        print(f'Объект {obj} не является вызываемым')
Объект 123 не является вызываемым
Вызов greet: Hello
Объект text не является вызываемым
Вызов <__main__.Multiplier object at 0x...>: 50
Вызов : 100

Проверка специальных дескрипторов.

Пример python
class DescriptorClass:
    @property
    def prop(self):
        return 'property'
    @staticmethod
    def static_meth():
        return 'static'
    @classmethod
    def class_meth(cls):
        return 'class method'

print('property callable?', callable(DescriptorClass.prop))
print('staticmethod callable?', callable(DescriptorClass.static_meth))
print('classmethod callable?', callable(DescriptorClass.class_meth))
property callable? False
staticmethod callable? True
classmethod callable? True

Использование внутри декоратора для проверки аргумента.

Пример python
def decorator_with_check(func):
    if not callable(func):
        raise TypeError('Декоратор ожидает вызываемый объект')
    def wrapper(*args, **kwargs):
        print('Вызов функции')
        return func(*args, **kwargs)
    return wrapper

@decorator_with_check
def valid_function():
    return 'OK'

# Попытка применить к невызываемому объекту вызовет ошибку
# @decorator_with_check
# class NotFunction:
#     pass

print(valid_function())
Вызов функции
OK

питон callable function comments

En
Callable Return whether the object is callable