1

I don't understand why when executing

def foo():
    pass

print(type(foo))
print(isinstance(foo, function))

The output is

<class 'function'>
NameError: name 'function' is not defined

But when executing

foo = list()

print(type(foo))
print(isinstance(foo, list))

The output is

<class 'list'>
True

Why does the first execution result in a NameError when function is clearly a valid class? Thanks in advance.

Valerii Boldakov
  • 1,751
  • 9
  • 19
Lukas Knudsen
  • 197
  • 2
  • 3
  • 14
  • 3
    Please check out this - https://stackoverflow.com/questions/624926/how-do-i-detect-whether-a-python-variable-is-a-function – Pawan Nov 23 '20 at 03:49
  • What do you not understand? There is no name `function` in the built-in namespace, and you haven't defined that variable anywhere. There is a type, though, which is the type of function objects. That exists. – juanpa.arrivillaga Nov 23 '20 at 04:00

1 Answers1

2

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.

ShadowRanger
  • 143,180
  • 12
  • 188
  • 271
  • It is *exposed*, it's just not in the built-in namespace. – juanpa.arrivillaga Nov 23 '20 at 03:59
  • @juanpa.arrivillaga: This one is *barely* exposed, and only insofar as *all* classes are exposed if you have access to their instances. I feel I made that fairly clear (in that I described what I meant by "not exposed" and showed you how you gain access to it). – ShadowRanger Nov 23 '20 at 17:43