Why is `function` not a keyword in Python?

Viewed 1889

Classes like str or type

>>> type("pear")
<class 'str'>
>>> type(str)
<class 'type'>

are accessible in Python:

>>> str
<class 'str'>
>>> type
<class 'type'>

However, classes function and builtin_function_or_method are not.

>>> def foo(): pass
... 
>>> type(foo)
<class 'function'>
>>> type(print)
<class 'builtin_function_or_method'>

They appear as builtin classes but trying to access them throws name errors:

>>> function
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'function' is not defined
>>> builtin_function_or_method
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'builtin_function_or_method' is not defined

What's special about function and builtin_function_or_method ?

3 Answers

What you are seeing is the representation of the function type:

>>> from types import FunctionType
>>> repr(FunctionType)
"<class 'function'>"

This is the "type" of a function defined with def or otherwise:

>>> def f():
...     pass
... 
>>> type(f) is FunctionType
True
>>> type(lambda: None) is FunctionType
True

The string you've seen in the representation is coming from __name__ attribute on each object:

>>> type(print).__name__
'builtin_function_or_method'
>>> FunctionType.__name__
'function'

"function" is not syntax itself, because it's easier to type "def".

A rhetorical question: if def was the name used to resolve to the function type, then what syntax would you use to actually define a function?

Classes and functions have an inherent name:

>>> def foo():
...     pass
...
>>> foo
<function foo at 0x10f951400>
>>> foo.__name__
'foo'

The name attached to the object is independent of the name you use to access the object, though when defining functions (and classes), they are the same.

>>> bar = foo
>>> bar
<function foo at 0x10f951400>

You can even get rid of the variable you use to access the function, as long as you have a reference somewhere else:

>>> funcs = [foo]
>>> funcs[0]
<function foo at 0x10f951400>
>>> del foo
>>> foo
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'foo' is not defined
>>> funcs[0]
<function foo at 0x10f951400>
>>> funcs[0].__name__
'foo'

The built-in function type is like this: there is no variable that refers to it, but it still exists, and has a __name__:

>>> def foo(): pass
...
>>> type(foo)
<class 'function'>
>>> type(foo).__name__
'function'

A Type Object is returned from the type() function (or object.__class__).

You can get a full list of these type objects here.

But you can also create your own:

>>> import types
>>> types.new_class('my_made_up_type')
<class 'types.my_made_up_type'>

So it is a type object that certain objects (like built-in functions) return (namely: types.BuiltinFunctionType) , but these type objects are not built-in classes, so it is no wonder they are not defined in the interpreter.

Related