On non-builtin types, types.FunctionType
and types.MethodType
behave as expected:
>>> isinstance(MyClass.func, FunctionType)
True
>>> isinstance(MyClass.func, MethodType)
False
>>> isinstance(MyClass().func, FunctionType)
False
>>> isinstance(MyClass().func, MethodType)
True
However, on a built-in type, BuiltinFunctionType
and BuiltinMethodType
don't behave accordingly:
>>> isinstance(list.append, (FunctionType, MethodType,
... BuiltinFunctionType, BuiltinMethodType))
False <- Why??
>>> isinstance([].append, (FunctionType, MethodType))
False
>>> isinstance([].append, BuiltinFunctionType)
True <- Why??
>>> isinstance([].append, BuiltinMethodType)
True
现在这没有意义,对吗?有人可以解释吗?
EDIT: isinstance(list.append, MethodDescriptorType) == True
. Can someone explain how MethodDescriptorType
differs from BuiltinMethodType
and why do we need it? The official documentation doesn't really say much.
BuiltinFunctionType
andBuiltinMethodType
are just different names referring to the same object:isinstance(list.append, BuiltinMethodType)
is false because it's not a method (i.e. an instance method bound to some object). For custom classes the method binding happens throughobject.__getattribute__
, so the functions defined with a class are just plain functions:and hence
isinstance(MyClass.func, FunctionType)
. This works because all functions are non-data descriptors:For builtin types these objects (e.g.
list.append
) are also dedicated descriptors that handle the binding to their objects. Sox = []; x.append
returns a bound method which was created by the descriptorlist.append
and bound to the objectx
: