Python 类级classmethod()只能在方法\描述符或实例方法上调用

Python 类级classmethod()只能在方法\描述符或实例方法上调用,python,cython,Python,Cython,util.py: 导入检查 类单例(类型): _实例=[] 定义调用(cls、*ARG、**kwargs): 如果cls不在cls.\u实例中: cls._实例[cls]=super(单例,cls)。_调用(*args,**kwargs) 类元结果(单例): def uu getattribute(cls,名称): 返回super()。\uuuu getattribute\uuuu(名称) 类结果(元类=元结果): @静力学方法 def res_decorator(func): def func

util.py:

导入检查
类单例(类型):
_实例=[]
定义调用(cls、*ARG、**kwargs):
如果cls不在cls.\u实例中:
cls._实例[cls]=super(单例,cls)。_调用(*args,**kwargs)
类元结果(单例):
def uu getattribute(cls,名称):
返回super()。\uuuu getattribute\uuuu(名称)
类结果(元类=元结果):
@静力学方法
def res_decorator(func):
def funcwrap(*参数,**kwargs):
sig=检查签名(func)
绑定_sig=sig.bind(*args,**kwargs)
绑定符号应用默认值()
#提取函数参数的附加代码
回卷
检查_params.py

从util导入结果作为\u结果
从abc进口ABCMeta作为_ABCMeta
类paramparse(元类=_ABCMeta)
@类方法
@_Result.resu装饰器
def解析\闪存\参数(cls、闪存\配置\路径):
#一些代码
现在,我使用以下设置将文件check_params.py循环化:

cythonize.py

将操作系统作为操作系统导入
从pathlib导入路径为_路径
从distutils.core导入设置为\u设置
从Cython.Distutils导入build\u ext作为\u build\u ext
文件\u到\u编译=[]
def cython_构建(源路径):
对于dirpath,u,os.walk中的fname(源路径):
如果f.endswith('.py'),则[x中的fname代表fname中的x]:
fname=_路径(fname)
文件\u to \u compile.append(fname)
对于要编译的文件中的e:
e、 cython_指令={'binding':True,'language_level':3}
_安装程序(name=“Proj1”,cmdclass={'build\u ext':\u build\u ext},ext\u modules=要编译的文件)
cythonized为: python cythonize.py--路径C:\directory\u,其中\u check\u params\u存在

生成一个pyd文件,尝试在该文件上运行以下单元测试:

现在,在单元测试中讨论用法:

单元测试检查参数

来自check_params import*#此处获取错误,代码之外的详细信息
#这里写的单元测试
检查参数。pyx:112:在初始检查参数中 ??? E
TypeError:只能对方法描述符或实例方法调用类级别的classmethod()。

因此,当我调试这个程序时,这个错误似乎是由于check_params.py中的类方法描述符覆盖decorator(def parse_flash_params)引起的


如果您需要更多信息,请告诉我。

这仍然不是一个非常有用的示例,因为您提供的代码实际上仍然不起作用。但是:

案件

@classmethod
@_Result.res_decorator
是一个Cython bug。在Cython中,有很多类型检查来确保类型是一个方法(类中定义的函数),而实际上它只需要是可调用的,这应该只在调用时进行检查。作为一个快速解决方法,您可以编辑相关的内部Cython文件(CythonFunction.c)来替换这些行

PyErr_SetString(PyExc_TypeError,
               "Class-level classmethod() can only be called on "
               "a method_descriptor or instance method.");
return NULL;

在我看来,这更接近Python的功能,它接受任何对象,并且只在实际调用函数时检查可调用性

从长远来看,你应该用一个实际有效的例子来演示这个问题。通过这种方式,它实际上可以被修复。我认为你不需要
Result
,而staticclass bit-
res\u decorator
作为一个独立的函数应该演示这个问题


第二种可能的顺序

@_Result.res_decorator
@classmethod
由于
classmethod
decorator的直接结果是不可调用的,因此它也不适用于未经语法化的Python。它只有在成为绑定方法时才可调用,以后才会发生。因此,这不是Cython中的错误


最后增编:

一个更干净的解决方法是强制Cython使用内置的classmethod,而不是它自己的导致bug的版本

try:
    myclassmethod = __builtins__.classmethod
except AttributeError:
    myclassmethod = __builtins__['classmethod']

class paramparse(metaclass=_ABCMeta):

    @myclassmethod
    @_Result.res_decorator
    def parse_flash_params(cls, flash_config_path):
        pass

try…except
块是因为在Cython和Python模块中,
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuz>的行为稍有不同,这很好,因为这是一个实现细节。

什么是
Singletonclass1.decorator1
?请发布一些我们可以实际运行的东西,在运行时会重现问题。这是一个Singletonclass1中定义的decorator是一个单例类。我认为我们可以先尝试一个简单的decorator。
@classmethod
在Cython中工作得很好。简单的decorator在Cython中工作得很好。简单的decorator与classmethod结合在一起可以按任意顺序工作。这个问题无法回答。请阅读并编辑it.Hi@DavidW,请检查更新后的问题。我试图尽可能地最小化,同时仍在尝试理解。你的cythonize.py在中有一些语法错误,因此不起作用。正如check_paramsI实际上注意到的那样,这很公平……是的@DavidW,我编辑了问题以删除语法错误。你的一切都是对的。我试图更改代码,它成功了。重新定义类方法的变通方法也同样有效。该变通方法将导致cdef类中大多数类方法的性能下降,因为它将导致Cython使用普通的Python类方法类型,而不是为C类方法设计的类方法类型。@user2357112 Fair point。更好的解决方法可能是只将设置异常的代码替换为
return PyClassMethod\u New(method);
事实上,这不是性能回归,我认为当classmethod委托给需要实例而不是类的PyMethodDescrObject时,可能会导致类型错误。(无论问题是性能回归还是错误,仅替换异常设置代码都可以避免该问题。)
try:
    myclassmethod = __builtins__.classmethod
except AttributeError:
    myclassmethod = __builtins__['classmethod']

class paramparse(metaclass=_ABCMeta):

    @myclassmethod
    @_Result.res_decorator
    def parse_flash_params(cls, flash_config_path):
        pass