Python中的函数是一个类的对象吗?

7
我读到在Python中,一个函数是一个类的对象。为了更好地理解,我做了如下操作:
>>> 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

问:为什么解释器在第二种情况下会抛出错误,而不是在第一种情况下?我原本期望它返回<type 'type'>。请纠正我的理解。


4
Python 中 一切皆对象 - juanpa.arrivillaga
2
在您的第二种情况下,function 不是一个已定义的名称,这就是为什么它会引发异常的原因。您想要做的是 function = T1.__class__; function.__class__ 或者 T1.__class__.__class_ - Vincent Savard
2
更好的说法是,“在Python中,函数是类的一个实例”。 - heltonbiker
2个回答

6

有一个函数类型,但没有内置名称。您可以在types模块下找到另一个参考:

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

所以,这里唯一的区别是function不是内置名称,不像int等名称。如果出于某种原因您想要该名称在您的命名空间中,您可以将其绑定:
>>> function = type(lambda: 0)
>>> function
<class 'function'>

为什么 T1.class.class 不会抛出错误?请原谅我的无知。 - fsociety
1
@fsociety 因为T1有一个类,即type。在Python中,所有东西都是对象 - juanpa.arrivillaga
我不确定为什么 "'isinstance(T1.class, types.FunctionType)'" 会是“False”? - Tom J
1
@TomJ T1.__class__types.FunctionType,而不是一个实例。T1 本身是一个函数实例,因此 isinstance(T1, types.FunctionType) - wim

1
想象一下,假设你创建了自己的元类(类的类),以及该元类的子类(它本身也是一个类):
>>> 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'>

现在,我们将删除标识符MyMeta:

>>> del MyMeta

即使 MyMeta 已被删除,您仍然可以访问由其表示的元类对象。当然:

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

因此,在MyClass字典中仍然存在对元类对象的引用。

但是,name MyMeta现在无效,因为它已被删除:

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

重要提示:元类名称已被删除,而不是元类对象本身。

因此,您仍然可以通过以下方式访问元类对象

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

对于函数名称(本身有点像内置的元类;即,它是函数对象的类或类型),情况也是如此——默认情况下,在交互式 Python 会话中,名称 function 不存在。但是对象仍然存在。您可以通过以下方式访问它:

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

如果您愿意,甚至可以将名称 function 分配给函数<class 'type'>对象(虽然没有太多理由这样做):
>>> function  = f.__class__
>>> print(function)
<class 'function'>
>>> print(function.__class__)
<class 'type'>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接