object.__dict__
和其他地方的隐藏方法设置如下:
<dictproxy {'__add__': <slot wrapper '__add__' of 'instance' objects>,
'__and__': <slot wrapper '__and__' of 'instance' objects>,
'__call__': <slot wrapper '__call__' of 'instance' objects>,
'__cmp__': <slot wrapper '__cmp__' of 'instance' objects>,
'__coerce__': <slot wrapper '__coerce__' of 'instance' objects>,
'__contains__': <slot wrapper '__contains__' of 'instance' objects>,
'__delattr__': <slot wrapper '__delattr__' of 'instance' objects>,
'__delitem__': <slot wrapper '__delitem__' of 'instance' objects>,
'__delslice__': <slot wrapper '__delslice__' of 'instance' objects>,
'__div__': <slot wrapper '__div__' of 'instance' objects>,
'__divmod__': <slot wrapper '__divmod__' of 'instance' objects>,
...
这些是什么,它们是用来做什么的?
编辑:这是的输出
class A:
pass
b = A()
print(type(b).__dict__)
根据https://doc.sagemath.org/html/en/reference/cpython/sage/cpython/wrapperdescr.html:
插槽包装器安装在扩展类型的dict中,以访问在C中实现的特殊方法。例如,object__init__或Integer__lt__。请注意,槽包装器总是未绑定的(有一个绑定的变体称为方法包装器(。
因此,它们实际上是覆盖对象的C实现方法的方法。Python中的许多神奇方法和属性都是通过C对象上的槽包装器实现的。由于Python的大多数实现都是用C编写的,所以这是有道理的。
object
类,因为它是类层次结构的基类。可以肯定地推断,它的底层代码是为了执行良好而编写的。
在CPython中,python的实现是用C和python编写的。底层代码是用C编写的,以满足性能需求。
但是,如何管理和处理从python脚本到某个C编译的二进制文件中的函数指针的调用??
显然,例如对repr(b)
的调用将遵循以下逻辑:
- 检查绑定方法的名称
__repr__
是否存在于b.__dict__
中,然后尝试调用它 - 如果找不到,请在其类
type(b).__dict__
(相当于A.__dict__
(下搜索名称 - 如果没有找到,那么它将在其超级类下进行搜索。
A.__base__
,在我们的例子中是类object
。并且由于hasattr(object, '__repr__')==True
,查找将通过返回绑定方法object.__repr__
来完成,该绑定方法是作为类wrapper_descriptor
的实例的槽包装器 - 然后,包装器将处理必要的东西(获取对象b的详细信息,获取指向C函数的指针,传递必要的参数,处理异常和错误…(
因此,它几乎是一个包装器,它使用CPython自己的内置API来避免我们的头痛,并在两种语言的逻辑之间进行分离。
最后一个例子显示两次相同的调用:
>>> object.__repr__(b)
'<__main__.A object at 0x011EE5C8>'
>>> repr(b)
'<__main__.A object at 0x011EE5C8>'
它是一种内部类型,用于某些可调用对象,即内置类上的方法。它为什么不同于函数或任何其他可调用函数并不重要。您也可以将其作为对象上的方法来调用。