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

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.

评论
uautem
uautem

BuiltinFunctionType and BuiltinMethodType are just different names referring to the same object:

>>> BuiltinFunctionType is BuiltinMethodType
True

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 through object.__getattribute__, so the functions defined with a class are just plain functions:

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

and hence isinstance(MyClass.func, FunctionType). This works because all functions are non-data descriptors:

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

For builtin types these objects (e.g. list.append) are also dedicated descriptors that handle the binding to their objects. So x = []; x.append returns a bound method which was created by the descriptor list.append and bound to the object x:

>>> type(list.append)
<class 'method_descriptor'>
点赞
评论