Python扩展类型:super()在基类中找不到方法(也称为属性)

Python扩展类型:super()在基类中找不到方法(也称为属性),python,derived-class,base-class,getattr,Python,Derived Class,Base Class,Getattr,我是PyCXX,它是Python的C++包装器。 向新样式类添加方法的原始(工作)实现涉及为每个类创建一个“extern C”处理程序函数,用指向这些处理程序的指针填充PyMethodDef表,并将PyTypeObject的表->tp_方法放置到此表 >我用一个重写GETTARO的机制来替换这个机制,搜索我自己的数据,看看这个属性是否有一个相应的C++方法,如果这样的话,它就被封装成一个可调用的Python对象并返回它,否则推迟到pyObjtTeNoGeGETAuto.< /P> 如果我创建了

我是PyCXX,它是Python的C++包装器。 向新样式类添加方法的原始(工作)实现涉及为每个类创建一个“extern C”处理程序函数,用指向这些处理程序的指针填充PyMethodDef表,并将PyTypeObject的表->tp_方法放置到此表

<> >我用一个重写GETTARO的机制来替换这个机制,搜索我自己的数据,看看这个属性是否有一个相应的C++方法,如果这样的话,它就被封装成一个可调用的Python对象并返回它,否则推迟到pyObjtTeNoGeGETAuto.< /P> 如果我创建了一个新的\u样式\u类的实例,则此技术有效:

# new_style_class is a C++ class deriving from ExtObj_new
_new_style_class = simple.new_style_class()
_new_style_class.func_noargs()
但是,如果我尝试从新样式类派生并从基调用func_noargs(),如下所示:

print( '--- Derived func ---' )
class Derived(simple.new_style_class):
    def __init__( self ):
        simple.new_style_class.__init__( self )

    def derived_func( self ):
        print( 'derived_func' )
        print( vars(super()) )
        super().func_noargs() # <-- AttributeError: 'super' object has no attribute 'func_noargs'

d = Derived()
d.derived_func()
print('----派生函数--')
派生类(简单。新的\u样式\u类):
定义初始化(自):
简单。新样式的类。初始化(self)
def派生函数(自):
打印('derived_func')
打印(变量(super())
super().func_noargs()#引用
已弃用,因此最好决定使用。但这根本不是正确的方法。查看Python的
Objects/typeobject.c
源文件,您将找到
super
类型的定义,以及定义类型方法的静态函数
add\u methods
。这三者一起说明了为什么你会遇到问题

为什么不使用
tp\u getattro
来“定义”方法 通常可以方便地将此字段设置为
PyObject\u GenericGetAttr()
,这实现了查找对象属性的常规方法

因此,只为对象定义查找,而不为类型定义查找,但应为类型定义方法

如何定义方法 函数
add_methods
迭代
tp_methods
,使用
PyDescr_NewMethod
定义每个方法(对于静态方法,
PyCFunction_New
),并将其添加到类型对象的字典中

super
如何搜索方法 超级类型定义了
tp\u getattro
。现在
super().func\u noargs()
将触发超级对象中的
func\u noargs
查找。这意味着将在每个相关超类型的字典中查找
func_noargs
。如果未找到任何内容、请求了
\uuuuu class\uuuuuuu
或未定义
super
的第二个参数或
None
,超级对象将在自身上调用
PyObject\u GenericGetAttr
。因此,永远不会调用您的
tp\u getattro

结论
如果您不喜欢原始(工作)解决方案,应将
tp_getattro
中返回的函数放入类型对象的字典中。

请向我们显示声明
func_noargs()
的确切代码。如果它只是一个可调用的实例属性,
super()
可能找不到它。换句话说,如果希望
super()
工作,则此代码必须工作:
simple.new\u style\u class.func\u noargs(实例)