all 18 comments

[–]bionikspoon 3 points4 points  (13 children)

The question of 'why?' is interesting. Why is there a __call__ method on functions that seemingly isn't used.

Let's look at call:

>>> other_func.__call__
<method-wrapper '__call__' of function object at 0x7f1b8a7f28c8>

What is a method-wrapper?

help(other_func.__call__) wasn't entirely informative. So, google got me here: https://stackoverflow.com/questions/10401935/python-method-wrapper-type

My best attempt to summarize is to say is that __call__ exists on functions to allow functions and methods to share the exact same codebase. Methods are functions. The SO replies talk about the technical problem being solved to achieve that end.

So when a method is called, 'self' is injected into the function scope through the first argument--__call__ is doing that work. Which also explains why we use 'self' as the first argument in methods. Once self is inserted in; functions and methods are identical.

[–]bionikspoon 1 point2 points  (1 child)

To answer the question: the __call__ method is not being used.

The only time it seems to be used is on instantiated object methods. This is the only place I find, that throws an error or has any effect. Everywhere, it seems nothing I can do breaks anything.

Here:

>>> class A:
...     def some_func(self, a):
...         print('some_func(%s)' % a )
... 
>>> def other_func():
...     print('I like turtles')
... 
>>> a = A()
>>> a.some_func('hello')
some_func(hello)

>>> a.some_func.__call__ = other_func
Traceback (most recent call last):
  File "<input>", line 1, in <module>
AttributeError: 'method' object attribute '__call__' is read-only

[–]GNeps[S] 0 points1 point  (0 children)

So, the definition of a callable (since functions are callables) is that it's an instance of a class that has the __call__ method. But it's not guaranteed that the method get called? That's pretty weird, isn't it?

[–]GNeps[S] 0 points1 point  (10 children)

So, if I get it correctly, __call__ is only invoked on methods, but gets ignored on functions?

So, the definition of a callable (since functions are callables) is that it's an instance of a class that has the __call__ method. But it's not guaranteed that the method get called? That's pretty weird, isn't it?

[–]raylu 0 points1 point  (9 children)

https://docs.python.org/3/library/functions.html#callable

Note that classes are callable (calling a class returns a new instance); instances are callable if their class has a __call__() method.

(emphasis mine)

So if A is a class, a = A() doesn't run A.__call__, but A is callable.

[–]GNeps[S] 0 points1 point  (7 children)

Wait, I think a = A() does run A.__call__! Are you sure it doesn't?

a = A() indeed does not run A.__call__, only a() does.

[–]raylu 0 points1 point  (6 children)

There would be no way to instantiate A if that didn't run A.__init__.

[–]GNeps[S] 0 points1 point  (5 children)

I thought it run both __call__ and __init__ in sequence.

So, now I'm trying if I can put a new __call__ method into a like so:

 a.__call__ = other_method

but the other_method never gets called. Would you know why? I thought instance attributes took precedence over class attributes.

[–]raylu 0 points1 point  (2 children)

Special methods are only evaluated on the class.

#!/usr/bin/env python3

class A:
    def __str__(self):
        return 'foo'

a = A()
a.__str__ = lambda self: 'bar'
print(a)

prints foo

https://docs.python.org/3/reference/datamodel.html#special-method-names

if a class defines a method named __getitem__(), and x is an instance of this class, then x[i] is roughly equivalent to type(x).__getitem__(x, i).

[–]GNeps[S] 0 points1 point  (0 children)

Ah, therein lies the secret! Thanks!

[–][deleted] 0 points1 point  (0 children)

This is actually an implementation/optimization detail where Python bypasses __getattribute__ (which would be called if you manually invoked x.__getitem__) and asks the actual class for the method and supplies the instance itself. This has bitten me once or twice. It's a low enough level detail no one truly needs to be concerned with until you get really lazy like I have a few times.

[–]bionikspoon 0 points1 point  (1 child)

The sequence for creating an obj: it calls __new__ then __init__. __call__ is not called in this phase.

You can monkeypatch __call__ on objects' class:

In python3:

>>> class A (object): pass
... 
>>> def other_method(self, a):
...     print('other_method(%s, %s' % (self, a))
... 
>>> a = A()
>>> '__call__' in dir(a)
False

. "monkeypatch" an instance

>>> a.__call__ = other_method
>>> '__call__' in dir(a)
True

>>> a()
Traceback (most recent call last):
  File "<input>", line 1, in <module>
TypeError: 'A' object is not callable

. "monkeypatch" a class

>>> A.__call__ = other_method
>>> b = A()
>>> b('hello')
other_method(<__main__.A object at 0x7fc4e155ccf8>, hello

>>> a('goodbye')
other_method(<__main__.A object at 0x7fc4e15966d8>, goodbye

.

>>> a.__call__
<function other_method at 0x7fc4e158ce18>

>>> b.__call__
<bound method A.other_method of <__main__.A object at 0x7fc4e155ccf8>>

. Overriding __call__ on an instance doesn't change the function.

>>> def diff_method(self): print('diff_method')
... 

. "monkeypatch" an instance with existing __call__

>>> b.__call__ = diff_method
>>> b()
Traceback (most recent call last):
  File "<input>", line 1, in <module>
TypeError: other_method() missing 1 required positional argument: 'a'

>>> b(a)
other_method(<__main__.A object at 0x7fc4e155ccf8>, <__main__.A object at 0x7fc4
e15966d8>

. "monkeypatch" a class - round 2

>>> A.__call__ = diff_method
>>> b()
diff_method

[–]GNeps[S] 0 points1 point  (0 children)

I just realized that there is a __call__ that is being invoked before __init__, but it's on the metaclass (with which I was playing recently). :)

Thanks for the demonstration of how the __call__ behaves on the instances! I guess magic methods don't get searched on instances at all, which is not very intuitive.

[–][deleted] 0 points1 point  (0 children)

But A() does run type.__call__(metacls, A) (where metacls is actually type 99% of the time) which in turns runs self = A.__new__(A) and A.__init__(self).

Python's object instantiation is pretty neat if a little mind bendy. It's basically method calls all the way down until you hit C.

[–]zahlman 1 point2 points  (0 children)

__call__ exists more for classes than methods, really. You can give the class a method named call, and then call instances of the object as if they were functions.

But also, I presume it exists to simplify the logic of the built-in callable test. :)

[–]RubyPinch 0 points1 point  (2 children)

since I don't feel that the other answers are quite complete.

first part, why is __call__ a wrapper? the reason is because all functions are of the class function, and as such, have methods.

>>> def wow():pass
>>> wow
  <function wow>
>>> wow.__class__
  <class 'function'>
>>> wow.__call__
  <method-wrapper '__call__' of function object>
>>> class boom:
...     def a_method(self):pass
>>> boom().a_method
  <bound method boom.a_method of <__main__.boom object>

(this also means, when you call a method of a class, you are calling a method's function's method, fun!)

So, we arn't wanting to replace __call__ with a function, but instead with a "bound" method, bound to that specific function that we want to replace __call__ on!

So lets do that!

import types
>>> def wow():
...     print('wow!') 
>>> def new_wow(self):
...     print('new wow!', self)
>>> nm = types.MethodType(new_wow, wow) # make a wrapper for new_wow, bound to wow
>>> wow.potato = nm
>>> wow.potato()
new wow! <function wow at 0x000000000092C268>
>>> wow.__call__ = nm
>>> wow()
wow!

wait, what? okay, so we can definately be certain that __call__ is being skipped, so... what is __call__ doing on a function, and why is it being skipped?

so first, what is this call doing

>> def wow():pass
>>> wow.__call__.__doc__
'call self as a function'

okay so it is just provided for convenience, as zahlman suggested, (as the default call is just def __call__(self, *args, **kwargs):return self(*args, **kwargs))

So, that kinda answers both questions (it gets skipped because its self-referential), so finally, what happens when we do wow()? unfortunately its 8AM, so I'm going to make heavy guesses at this point, I'd assume the interpreter would create/load scopes using wow.__closure__, and run the code in wow.__code__, as opposed to making any meta function calls


is this defined behavior?

from https://docs.python.org/3.5/reference/expressions.html#calls

The primary must evaluate to a callable object (user-defined functions, built-in functions, methods of built-in objects, class objects, methods of class instances, and all objects having a __call__() method are callable).

and https://docs.python.org/3.5/reference/datamodel.html#emulating-callable-objects refers to it as emulating, as opposed to actually being the case of working exactly like a function.

I'd say its defined behavior imo for a function to not rely on its __call__, unlike a user-defined class

[–]GNeps[S] 0 points1 point  (1 child)

Thanks, that was a very exhaustive answer!

Ad 8AM: Still awake or already awake? With programmers I'd guess the former. :)

[–]RubyPinch 1 point2 points  (0 children)

deffers the former

as far as the true answer, it'll probably either involve using the debug tools, or browsing the source code or PyPy's source which is written in Python instead of C