isinstance(list.append (BuiltinFunctionType, BuiltinMethodType)) == False

isinstance(list.append (BuiltinFunctionType, BuiltinMethodType)) == False

在非内置类型上,types.FunctionTypetypes.MethodType 的行为符合预期:

>>> isinstance(MyClass.func, FunctionType)
True
>>> isinstance(MyClass.func, MethodType)
False
>>> isinstance(MyClass().func, FunctionType)
False
>>> isinstance(MyClass().func, MethodType)
True

但是,在内置类型上,BuiltinFunctionTypeBuiltinMethodType 的行为并不相应:

>>> isinstance(list.append, (FunctionType, MethodType,
...                          BuiltinFunctionType, BuiltinMethodType))
False  <- Why??
>>> isinstance([].append, (FunctionType, MethodType))
False
>>> isinstance([].append, BuiltinFunctionType)
True  <- Why??
>>> isinstance([].append, BuiltinMethodType)
True

现在这没有意义,是吗?有人可以解释一下吗?

编辑:isinstance(list.append, MethodDescriptorType) == True。谁能解释一下 MethodDescriptorTypeBuiltinMethodType 的区别以及我们为什么需要它? official documentation 真的没什么好说的。

BuiltinFunctionTypeBuiltinMethodType 只是引用同一对象的不同名称:

>>> BuiltinFunctionType is BuiltinMethodType
True

isinstance(list.append, BuiltinMethodType) 为假,因为它不是方法(即绑定到某个对象的实例方法)。方法绑定通过 object.__getattribute__ 发生,所以用 class 定义的函数只是普通函数:

>>> def func(x): pass
... 
>>> class MyClass: func = func
... 
>>> MyClass.func is func
True

因此 isinstance(MyClass.func, FunctionType)。这是有效的,因为所有功能都是 non-data descriptors:

>>> func.__get__
<method-wrapper '__get__' of function object at 0x7f80abe57400>

对于内置类型,这些对象(例如 list.append)也是处理与其对象绑定的专用描述符。所以 x = []; x.append returns 由描述符 list.append 创建并绑定到对象 x:

的绑定方法
>>> type(list.append)
<class 'method_descriptor'>