什么是 python 中的'slot wrapper'?



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)的调用将遵循以下逻辑:

  1. 检查绑定方法的名称__repr__是否存在于b.__dict__中,然后尝试调用它
  2. 如果找不到,请在其类type(b).__dict__(相当于A.__dict__(下搜索名称
  3. 如果没有找到,那么它将在其超级类下进行搜索。A.__base__,在我们的例子中是类object。并且由于hasattr(object, '__repr__')==True,查找将通过返回绑定方法object.__repr__来完成,该绑定方法是作为类wrapper_descriptor的实例的槽包装器
  4. 然后,包装器将处理必要的东西(获取对象b的详细信息,获取指向C函数的指针,传递必要的参数,处理异常和错误…(

因此,它几乎是一个包装器,它使用CPython自己的内置API来避免我们的头痛,并在两种语言的逻辑之间进行分离。

最后一个例子显示两次相同的调用:

>>> object.__repr__(b)
'<__main__.A object at 0x011EE5C8>'
>>> repr(b)
'<__main__.A object at 0x011EE5C8>'

它是一种内部类型,用于某些可调用对象,即内置类上的方法。它为什么不同于函数或任何其他可调用函数并不重要。您也可以将其作为对象上的方法来调用。

最新更新