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

如何在Python/Cython中让isinstance判定自定义类为float类型?

解决方案

方法1:通过抽象基类注册(Python/Cython通用)

Python的numbers模块提供了数值类型的抽象基类,float属于numbers.Real的子类。将自定义类注册为numbers.Real的虚拟子类后,pytest.approx会识别并处理近似比较(其底层逻辑兼容Real类型):

from numbers import Real

class Angle:
    def __init__(self, value):
        self.value = max(0.0, min(360.0, float(value)))
    
    def __float__(self):
        return self.value

# 注册为Real的虚拟子类
Real.register(Angle)

此时isinstance(Angle(90), Real)返回True,pytest.approx能正常执行近似校验。

方法2:自定义元类修改isinstance行为(仅Python)

若必须让isinstance(obj, float)返回True,可通过自定义元类重写__instancecheck__方法,但这种方式属于“类型欺骗”,可能引发兼容性问题,需谨慎使用:

class FloatMeta(type):
    def __instancecheck__(cls, instance):
        return isinstance(instance, float) or isinstance(instance, Angle)

class Angle(metaclass=FloatMeta):
    def __init__(self, value):
        self.value = max(0.0, min(360.0, float(value)))
    
    def __float__(self):
        return self.value

执行isinstance(Angle(90), float)会返回True,但依赖float严格类型检查的代码可能出现异常。

方法3:适配pytest.approx的自定义比较(更安全)

无需修改isinstance行为,直接让自定义类支持pytest.approx的比较逻辑,这种方式不会破坏原生类型检查规则:

from pytest import approx

class Angle:
    def __init__(self, value):
        self.value = max(0.0, min(360.0, float(value)))
    
    def __float__(self):
        return self.value
    
    def __eq__(self, other):
        if isinstance(other, approx.__class__):
            return float(self) == other
        return float(self) == other
    
    # 或实现pytest规范的__approx__方法
    def __approx__(self, other, rel=None, abs=None):
        if rel is not None:
            return abs(float(self) - float(other)) <= max(rel * abs(float(other)), abs)
        return abs(float(self) - float(other)) <= abs

Cython扩展类型的特殊处理

在Cython中,可直接沿用抽象基类注册的逻辑,或自定义类型的检查行为:

from cpython cimport PyObject
from numbers cimport Real

cdef class Angle:
    cdef double value
    
    def __init__(self, double value):
        if value <= 0:
            self.value = 0.0
        elif value >= 360:
            self.value = 360.0
        else:
            self.value = value
    
    def __float__(self):
        return self.value

# 注册为Real的虚拟子类
Real.register(Angle)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 14:35:22