7

I read that a function is an object of a class in python.To further understand, i did below:

>>> a=10
>>> a.__class__
<type 'int'>
>>> int.__class__
<type 'type'>
>>>
>>>
>>> def T1():
...     print 'test'
...
>>> T1.__class__
<type 'function'>
>>> function.__class__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'function' is not defined

Q:why does the interpreter throw an error in the second case and not in the first case? I was expecting it to return <type 'type'>.Please correct my understanding.

3
  • 4
    Everything is an object in Python. Commented Jan 30, 2017 at 18:16
  • 2
    In your second case, function is not a defined name, which is why it throws an exception. What you wanted to do was function = T1.__class__; function.__class__ or T1.__class__.__class_. Commented Jan 30, 2017 at 18:20
  • 2
    A better way to say it is "a function is an instance of a class in python". Commented Jan 30, 2017 at 18:26

2 Answers 2

6

There is a function type, but there is no built-in name for it. You can find another reference there under the types module:

>>> import types
>>> def T1():
...     pass
...     
>>> T1.__class__ is types.FunctionType
True
>>> print(repr(types.FunctionType))
<class 'function'>

So, the only difference here is that function is not a built-in name, unlike names such as int. If you want that name in your namespace for some reason, you can just bind it:

>>> function = type(lambda: 0)
>>> function
<class 'function'>
Sign up to request clarification or add additional context in comments.

4 Comments

why does T1.__class__.__class__ does not throw error?Pardon my ignorance
@fsociety Because the class of T1 also has a class, which is type. Everything in Python is an object.
I am not sure why 'isinstance(T1.__class__, types.FunctionType)' is 'False'?
@TomJ T1.__class__ is types.FunctionType, not an instance. T1 itself is a function instance, so isinstance(T1, types.FunctionType)
1

Think of it this way. Say you create your own metaclass (class of a class), and a subclass of your metaclass (which is itself just a class):

>>> class MyMeta(type): # <-- a custom metaclass, similar to function
        pass

>>> print(MyMeta.__name__)
MyMeta
>>> print(__class__)
<class 'type'>

>>> class MyClass(metaclass = MyMeta):
        pass
>>> print(MyClass.__class__)
<class 'MyMeta'>

Now, we will delete the identifier MyMeta:

>>> del MyMeta

Can you still get to the metaclass object that was represented by MyMeta although MyMeta has been deleted? Sure:

>>> print(MyClass.__class__)
<class 'MyMeta'>

So there is still a reference to the metaclass object in the MyClass dict.

However, the name MyMeta is now invalid, since it was deleted:

>>> class MyClassTwo(metaclass = MyMeta):
        pass
NameError!!
>>> print(MyMeta.__name__)
NameError!!
>>> print(MyMeta)
NameError!!

IMPORTANT: The metaclass name has been deleted, not the metaclass object itself.

Therefore you can still access the metaclass object this way:

>>> class MyClassTwo(metaclass = MyClass.__class__):
        pass

So it is with the function name (which is itself kind of like a built-in metaclass; i.e., it is the class, or type, of function objects)- by default, the name function doesn't exist in an interactive Python session. But the object does still exist. You can access it this way:

>>> def f(): pass
>>> f.__class__.__class__
<class 'type'>

And if you like, you can even go ahead and assign the name function to the function <class 'type'> object (although there's not much reason to do that):

>>> function  = f.__class__
>>> print(function)
<class 'function'>
>>> print(function.__class__)
<class 'type'>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.