function
is the name of the implementing class for user-defined functions, but it's not an exposed name (not part of the built-ins you can see anywhere).
For a similar example, imagine a module named foomodule.py
with these contents:
class Foo:
pass
def make_foo():
return Foo()
If you do this in another module:
from foomodule import make_foo
x = make_foo()
print(type(x))
it will tell you that it's a foomodule.Foo
. But if you do:
print(isinstance(x, foomodule.Foo))
you'll get a NameError
, because you can't actually see that qualified name in your current scope; it exists, but it's not "published" where you're looking for it (the current module's global scope).
In a similar way, the function
class the implements user-defined functions exists, but it's not directly published.
As it happens, you can find it published on the types
module as types.FunctionType
, but they get a reference to it the same way you did; by defining a user-defined function and calling type
on it. The type just isn't directly exposed at the Python level in any way shy of pulling it from an existing function with type
.
There are other examples of this in the built-ins, e.g. type(None)
is a class named NoneType
, but the only way to access it is via type(None)
; there's no reason to publish it directly. You can't manually make your own instances of NoneType
in a useful way; similarly, user-defined functions are made with def
, not the function
constructor.