37

I always hear this statement in Python (for topics such as decorators, etc. when you are passing functions, etc.) but have never really seen an elaboration on this.

For example is it possible to create a class c that has only one abstract method that is called with a set of opened and closed brackets.

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

so you can have

c(whatever parameters are required)

I could be way off the mark with my understanding here, I was just curious about what people meant by this.

Mehdi Charife
  • 722
  • 1
  • 7
  • 22
user3684792
  • 2,542
  • 2
  • 18
  • 23
  • 3
    `c(...)` creates a new object of type `c` by calling `__init__`. Once you have a new object, say for example `x`, calling `x()` calls `c.__call__`. – hlt Aug 13 '14 at 17:13
  • 1
    hmm, but when you write a function you don't need to create an instance of it to use it. Not sure what I am missing. – user3684792 Aug 13 '14 at 17:16
  • You don't need to create instances of *functions*. `c` is a *class*. – hlt Aug 13 '14 at 17:17
  • 1
    @user3684792: you don't have to use the `int()` or `str()` types to create integers either; you can create those by using syntax, string literals or int literals, too. `1` creates an object of type `int()`. Same with functions. – Martijn Pieters Aug 13 '14 at 17:24
  • @user3684792: perhaps you are thinking too much of instances here where you first have to create a class first. We already know how a function type should behave, Python provides that type (class) for you and takes care of those details. – Martijn Pieters Aug 13 '14 at 17:26
  • @hlt actually it creates it via `__new__` – wim Aug 13 '14 at 17:30
  • 3
    @hlt: actually, Python does create instances of a function type whenever you use a `def` statement or a `lambda` expression. It is just transparent and handled by the syntax. – Martijn Pieters Aug 13 '14 at 17:36
  • @MartijnPieters Yeah, that's why I said that *you* (as the programmer) don't have to... – hlt Aug 13 '14 at 17:37

2 Answers2

44

You are looking for the __call__ method. Function objects have that method:

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

Not that the Python interpreter loop actually makes use of that method when encountering a Python function object; optimisations in the implementation jump straight to the contained bytecode in most cases.

But you can use that on your own custom class:

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

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

Demo:

>>> 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 creates function objects for you when you use a def statement, or you use a lambda expression:

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

You can compare this to creating a string or an integer or a list using literal syntax:

listobject = [1, 'two']

The above creates 3 objects without ever calling a type, Python did that all for you based on the syntax used. The same applies to functions.

Creating one yourself can be a little more complex; you need to have a code object and reference to a global namespace, at the very least:

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

Here I created a function object by reusing the function type, taking the code object from the foo function; the function type is not a built-in name but the type really does exist and can be obtained by calling type() on an existing function instance.

I also passed in the global namespace of my interpreter, and a name; the latter is an optional argument; the name is otherwise taken from the code object.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • ok, this is interesting indeed. So you still need to initialise it first? Is there a way do get Callable('Hello'), as you would get with a function. I am not sure what is going on behind the scenes with functions – user3684792 Aug 13 '14 at 17:27
  • 1
    @user3684792: the interpreter handles creating function instances for you, on the whole you don't ever need to do that yourself. I already illustrate how to create a new instance of the function type; it takes a code object. Code objects contain Python bytecode and you now are really descending into the Python implementation; read the [Python datamodel document](https://docs.python.org/2/reference/datamodel.html) if you want to know the absolute nitty gritty of how that all fits together. – Martijn Pieters Aug 13 '14 at 17:30
  • 1
    aha - so the def statement effectively initialises the function object? – user3684792 Aug 13 '14 at 17:31
  • 2
    @user3684792: exactly. Just like other syntax creates a list object, or a dictionary, or a string or an integer. – Martijn Pieters Aug 13 '14 at 17:32
8

One simple way to see this is to create a function in the Python interpreter def bar(x): return x + 1 and then use dir(bar) to see the various magic attributes including __class__.

Yes, python functions are full objects.

For another approach, objects are functions if they have a magic __call__() method.

shapr
  • 1,676
  • 13
  • 18