Tim
Tim

Reputation: 99408

Do "static method object" and "class method object" not have "callable types"?

In Python Language Reference, Chapter 3 Datamodel, why is "instance method" listed under "callable types", while "static method object" and "class method object" are listed under "internal types"?

Callable types These are the types to which the function call operation (see section Calls) can be applied ...

Instance methods ...

Internal types A few types used internally by the interpreter are exposed to the user. Their definitions may change with future versions of the interpreter, but they are mentioned here for completeness. ...

Static method objects ...

Class method objects ...

Shouldn't static and class method objects also be callable types?

Upvotes: 2

Views: 819

Answers (2)

Dimitris Fasarakis Hilliard
Dimitris Fasarakis Hilliard

Reputation: 160377

No, staticmethod's and classmethods are not callable, no rationale to do so was found.

>>> def foo():
...     print("hello") 
>>> s = staticmethod(foo)
>>> s()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'staticmethod' object is not callable

They are meant to be invoked via the descriptor protocol and (usually) return a callable:

>>> s.__get__(foo)()
hello

this isn't the most common form, though. Usually a descriptor is invoked automatically upon attribute access, as the descriptor how-to states:

A descriptor can be called directly by its method name. For example, d.__get__(obj).

Alternatively, it is more common for a descriptor to be invoked automatically upon attribute access. For example, obj.d looks up d in the dictionary of obj. If d defines the method __get__(), then d.__get__(obj) is invoked according to the precedence rules listed below.

Upvotes: 5

The staticmethod objects are not callable:

Python 3.5.3 (default, Jan 19 2017, 14:11:04) 
[GCC 6.3.0 20170118] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> staticmethod(lambda x: print(x))
<staticmethod object at 0x7f8499f1ebe0>
>>> meth = staticmethod(lambda: print('static method called'))
>>> meth()
Traceback (most recent call last):

However they implement the descriptor protocol method __get__. The __get__ method then returns an actual callable object.

File "<stdin>", line 1, in <module>
TypeError: 'staticmethod' object is not callable
>>> meth.__get__(object, object())()
static method called

When you store the staticmethod object into a class attribute, and then look it up, the __get__ method is called implicitly.

Upvotes: 4

Related Questions