如何子类化numbers.Number并为LispNumber实例赋予初始值?
解决LispNumber继承numbers.Number的实现问题
首先明确:numbers.Number是Python的抽象基类(ABC),它仅定义数值类型的接口规范,本身不提供具体的数值实现逻辑。针对你的需求,提供两种实用方案:
方案1:包装数值并代理操作(适配Lisp系统需求)
如果需要LispNumber作为独立类型存在,同时兼容Python数值操作,不需要纠结super()调用(因为numbers.Number的__init__本就不需要参数)。可以通过包装内置数值、代理魔法方法的方式实现,既避免逻辑冗余,又能完整支持数值行为:
import numbers class LispNumber(numbers.Number): """兼容Lisp系统的数值类型,基于Python内置数值实现""" def __init__(self, thing): if not isinstance(thing, numbers.Number): raise TypeError(f"'{thing}' is not a Number") self.value = thing # 代理核心数值操作 def __add__(self, other): val = other.value if isinstance(other, LispNumber) else other return LispNumber(self.value + val) def __radd__(self, other): return self.__add__(other) def __sub__(self, other): val = other.value if isinstance(other, LispNumber) else other return LispNumber(self.value - val) def __rsub__(self, other): return LispNumber(other - self.value) def __mul__(self, other): val = other.value if isinstance(other, LispNumber) else other return LispNumber(self.value * val) def __rmul__(self, other): return self.__mul__(other) # 按需补充其他方法,比如除法、相等判断、打印 def __eq__(self, other): val = other.value if isinstance(other, LispNumber) else other return self.value == val def __repr__(self): return f"LispNumber({repr(self.value)})"
这里的value字段并非无用,它是LispNumber持有实际数值的载体,所有数值操作都基于它完成。如果需要更贴合Lisp风格,可将字段名改为_val或其他命名。
方案2:利用ABC注册机制(无额外包装)
如果不需要独立的LispNumber实例,仅需要让Python内置数值类型被识别为Lisp系统的数值类型,可以直接注册内置类型为LispNumber的虚拟子类:
import numbers class LispNumber(numbers.Number): pass # 将Python内置数值类型注册为LispNumber的子类 numbers.Integral.register(LispNumber) numbers.Real.register(LispNumber)
这样isinstance(5, LispNumber)、isinstance(3.14, LispNumber)都会返回True,无需额外创建包装对象。但这种方式仅适用于不需要添加Lisp特定逻辑的场景。
关于super()的说明
numbers.Number作为抽象基类,没有需要初始化的内部状态,因此你的自定义__init__不需要调用super().__init__()——直接处理自身的数值校验和字段赋值即可。
内容的提问来源于stack exchange,提问作者Bill Torcaso
相关产品推荐
相关产品推荐

