python - 超类中子类的自动初始化
问题描述
在 python 中的类内初始化子类中提出了类似的问题。那里的答案得出的结论是应该避免这种方法,我不确定这是否适用于以下情况,我想知道如何实现它,或者我应该做什么。
class Rational():
def __init__(self, numerator, denominator):
self.numerator = numerator
self.denominator = denominator
if self.denominator == 1:
pass
# >>> How to initialize as Integer in this case? <<<
# ... More methods for rationals
class Integer(Rational):
def __init__(self, value):
super().__init__(value, 1)
self.value = value
# ... More methods for integers
在这个文件中,我有简单的整数和Rational
数字类。由于所有Integer
s 都是有理数,Integer
是有理数的子类,我们调用super()
以允许整数调用有理数的方法。
Rational
不过,如果每当 a用分母 1 初始化时,它可以被自动识别为整数,那就太好了。例如,我想x = Rational(4, 1)
然后允许我调用x.integer_method()
甚至Integer(4) == x
返回 True。问题是,我不知道是否可以Integer
从初始化程序中调用初始化程序,Rational
因为我可能会陷入无限循环。
解决此问题的最佳方法是什么(通常不仅适用于整数和有理数,而且适用于任何父子类型,其中 Parent 的实例在初始化之前可能不会被识别为语义上等同于 Child 类型的成员?
解决方案
用于__new__
定义类的构造方式,包括构造其他类。避免定义__init__
,因为它不会在__new__
返回另一种类型的对象时自动调用。由于该方案将类强耦合在一起,Integer
因此可以避免要求super().__new__
简单。
class Rational():
def __new__(cls, numerator, denominator=1):
if denominator == 1:
return Integer(numerator)
self = object.__new__(cls)
self.numerator = numerator
self.denominator = denominator
return self # new always returns an instance
def __repr__(self):
return f'Rational({self.numerator}/{self.denominator})'
class Integer(Rational):
denominator = 1 # as a Rational, Integer must expose numerator and denominator
def __new__(cls, value):
self = object.__new__(cls)
self.numerator = value
return self
def __repr__(self):
return f'Integer({self.numerator})'
这足以动态构造适当的子类:
>>> Rational(12, 3)
Rational(12/3)
>>> Rational(15, 1)
Integer(15)
理想情况下,这样的类应该是不可变的;否则,Integer
作为 aRational
意味着它some_integer.denominator = 3
是有效的并产生Rational
具有 1/3 初始值的 a。
推荐阅读
- javascript - 如何使用 TypeScript 在 AWS-SDK 中动态调用方法?
- sql - 使用 where 条件的 SQL 子查询
- asp.net-core - SignalR - .Net Core 3 HubContext
- xamarin - Xamarin - 在 MAC 上安装 13.16.0.13 时出现问题
- c++ - 为什么g ++编译的代码会超出堆栈指针?
- python-3.x - 如何从 DB 烧瓶中获取列表
- javascript - 从反应函数返回 HTML
- django - django 开发人员如何判断哪个代码更好用
- javascript - Reactjs 中的高级设计问题:在发送到后端之前在组件之间传递上传文件数据
- php - 尝试比较数据库和 php 文件中的值