Являются ли функции объектами в Python?

Я всегда слышу это утверждение в Python (для таких тем, как декораторы и т.д., когда вы передаете функции и т.д.), но на самом деле никогда не видел разработки.

Например, возможно создать класс c, который имеет только один абстрактный метод, который вызывается с набором открытых и закрытых скобок.

i.e class c:
       @abstractmethod
       def method_to_be_called_by():
        ... 

чтобы вы могли

c(whatever parameters are required)

Я мог бы быть в стороне от моего понимания здесь, мне было просто интересно, что люди подразумевали под этим.

Ответы

Ответ 1

Вы ищете метод __call__. Объекты функции имеют этот метод:

>>> def foo(): pass
... 
>>> foo.__call__
<method-wrapper '__call__' of function object at 0x106aafd70>

Не то, чтобы цикл интерпретатора Python фактически использовал этот метод, когда сталкивался с объектом функции Python; оптимизация в реализации в большинстве случаев переходит прямо к содержащемуся байт-коду.

Но вы можете использовать это в своем собственном классе:

class Callable(object):
    def __init__(self, name):
        self.name = name

    def __call__(self, greeting):
        return '{}, {}!'.format(greeting, self.name)

Демо:

>>> class Callable(object):
...     def __init__(self, name):
...         self.name = name
...     def __call__(self, greeting):
...         return '{}, {}!'.format(greeting, self.name)
... 
>>> Callable('World')('Hello')
'Hello, World!'

Python создает объекты для вас, когда вы используете оператор def или используете lambda выражение:

>>> def foo(): pass
... 
>>> foo
<function foo at 0x106aafd70>
>>> lambda: None
<function <lambda> at 0x106d90668>

Вы можете сравнить это с созданием строки или целого числа или списка с использованием синтаксиса literal:

listobject = [1, 'two']

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

Создание одного может быть немного сложнее; вам нужно иметь объект кода и ссылку на глобальное пространство имен, по крайней мере:

>>> function_type = type(lambda: None)
>>> function_type
<type 'function'>
>>> function_type(foo.__code__, globals(), 'bar')
<function bar at 0x106d906e0>

Здесь я создал объект функции, повторно используя тип function, взяв объект кода из функции foo; тип функции не является встроенным именем, но тип действительно существует и может быть получен путем вызова type() в существующем экземпляре функции.

Я также передал в глобальном пространстве имен моего интерпретатора и имя; последний является необязательным аргументом; имя иначе берется из объекта кода.

Ответ 2

Один простой способ увидеть это - создать функцию в интерпретаторе Python def bar(x): return x + 1, а затем использовать dir(bar), чтобы увидеть различные магические атрибуты, включая __class__.

Да, функции python - это полные объекты.

Для другого подхода объекты являются функциями, если они имеют метод магии __call__().