You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Cython cdef类@property方法内访问其他@property返回0值问题

问题原因

核心问题出在cdef class的C属性声明逻辑:你在类开头写了cdef double distance, miles, meters, km,直接为类定义了4个C级别的实例属性,其中km、miles、meters和你后续用@property定义的属性完全重名。

Cython编译cdef类时的属性访问规则是:

  • 类内部的Cython代码访问self.xxx时,如果存在同名的C层属性,会直接通过内存偏移读取C属性值,完全不走Python的属性查找逻辑,也就不会触发你定义的@property描述符方法
  • cdef声明的C属性默认是私有状态,外部Python代码无法直接访问,因此外部访问同名属性时,会自动 fallback 到类上定义的@property方法

这就解释了你看到的所有现象:

  • __cinit__方法中你只给self.distance赋值了42.0,其余三个C属性miles、meters、km都是double类型,实例化时默认初始值为0.0
  • 在miles、meters属性方法内部写self.km时,Cython直接读取C层km属性的初始值0.0,根本没有调用你写的km属性方法,因此打印值为0,计算结果也为0
  • 外部IPython环境中访问Distance(42).km时,因为访问不到C层私有km属性,就触发了你定义的km property,返回self.distance的42.0,结果看似正常。
修复方案

删掉cdef声明中与property重名的C属性即可,只保留实际需要存储原生值的C属性:

import cython

cdef double MILES_PER_KILOMETER = 0.621371

cdef class Distance:
    # 仅保留实际存储值的C属性,移除miles、meters、km的C层声明
    cdef double distance

    def __cinit__(self, double distance) -> None:
        self.distance = distance

    @property
    def miles(self):
        print(self.km)
        return self.km * MILES_PER_KILOMETER

    @property
    def meters(self):
        print(self.km)
        return self.km * 1000.0

    @property
    def km(self):
        return self.distance

修改后类内部访问self.km时因为不存在同名C属性,就会正常触发km的property方法,返回正确的计算结果。


内容的提问来源于stack exchange,提问作者Jonathan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 05:51:14