How do Python tell “this is called as a function”? -


a callable object supposed defining __call__. class supposed object… or @ least exceptions. exception i'm failing formally clarify, question posted here.

let a simple class:

class a(object):      def call(*args):         return "in `call`"      def __call__(*args):         return "in `__call__`" 

the first function purposely named “call”, make clear purpose comparison other.

let's instantiate , forget expression implies:

a = a() # think of `a = magic` , forget `a()` 

now what's worth:

print(a.call()) print(a.call()) print(a()) print(a()) 

result in:

>>> in `call` >>> in `call` >>> <__main__.a object @ 0xnnnnnnnn> >>> in `__call__` 

the output (third statement not running __call__) not come surprise, when think every said “python class objects”…

this, more explicit, run __call__

print(a.__call__()) print(a.__call__())  >>> “in `__call__`” >>> “in `__call__`” 

all of show how a() may looks strange.

there exception in python rules, the documentation “object.call not lot __call__… not more that:

3.3.5. emulating callable objects

object.__call__(self[, args...]) 

called when instance “called” function; […]

but how python tell “it's called function” , honour or not object.__call__ rule?

this matter of type, type has object base class.

where can learn more (and formally) it?

by way, there difference here between python 2 , python 3?

----- %< ----- edit ----- >% -----

conclusions , other experiments after 1 answer , 1 comment

update #1

after @veedrac's answer , @chepner's comment, came other test, complete comments both:

class m(type):      def __call__(*args):         return "in `m.__call__`"  class a(object, metaclass=m):      def call(*args):         return "in `call`"      def __call__(*args):         return "in `a.__call__`"  print(a()) 

the result is:

>>> in `m.__call__` 

so seems that's meta‑class drives “call” operations. if understand correctly, meta‑class not matter class, classes instances.

update #2

another relevant test, shows not attribute of object matters, attribute of type of object:

class a(object):      def __call__(*args):         return "in `a.__call__`"  def call2(*args):     return "in `call2`"   = a()  print(a()) 

as expected, prints:

>>> in `a.__call__` 

now this:

a.__call__ = call2  print(a()) 

it prints:

>>> in `a.__call__` 

the same before attribute assigned. not print in call2, it's still in a.__call__. that's important note , explain why that's __call__ of meta‑class invoked (keep in mind meta‑class type of class object). __call__ used call function, not object, it's type.

x(*args, **kwargs) same type(x).__call__(x, *args, **kwargs).

so have

>>> type(a).__call__(a) <__main__.a object @ 0x7f4d88245b50> 

and makes sense.


chepner points out in comments type(a) == type. kind-of wierd, because type(a)(a) gives type again! remember we're instead using type(a).__call__(a) not same.

so resolves type.__call__(a). constructor function classes, builds data-structures , construction magic.


the same true of dunder (double underscore) methods, such __eq__. partially optimisation in cases.


Comments

Popular posts from this blog

javascript - how to protect a flash video from refresh? -

visual studio 2010 - Connect to informix database windows form application -

android - Associate same looper with different threads -