根据父 class 初始化的条件初始化子 class
Initializing a subclass on condition from the parent class initialisation
我正在为我在 Python 中编写的项目使用矩阵。我知道已经有很多用于处理矩阵的库,但我正在编写自己的库,所以我确切地知道引擎盖下发生了什么。
所以我有一个 Matrix
基础 class 和一个 Vector
子 class。两者都按预期单独工作,但如果用单行或单列初始化,我希望 Matrix
成为 Vector
。
当 Matrix
以正确的大小初始化时,我尝试了类似 self = Vector(...)
的方法。但这似乎并不影响对象。我也想过调用 Vector
class 的 __init__()
方法,但这还不够,因为我最想要的是 Vector
的方法。
是否有处理这种情况的 pythonic 方式?
这是可以做到的,尽管这可能不是最好的方法。毕竟如果 Matrix
class 被实例化,人们期望结果是一个 Matrix
实例。
实现这一点的一种方法是自定义 Matrix
class:
的构造函数
class Matrix:
def __new__(cls, nrows, ncols):
if nrows == 1:
inst = super(Matrix, cls).__new__(Vector)
else:
inst = super(Matrix, cls).__new__(cls)
inst.nrows = nrows
inst.ncols = ncols
return inst
def __repr__(self):
return '{}(nrows={}, ncols={})'.format(
self.__class__.__name__, self.nrows, self.ncols)
演示:
>>> m1 = Matrix(2, 5)
Matrix(nrows=2, ncols=5)
>>> Matrix(1, 5)
Vector(nrows=1, ncols=5)
请注意,实例实际上是在 __new__()
方法中创建的,而 __init__()
用于初始化新创建的实例。
此外,正如 @Blckknght 在下面的评论中提到的,通过 Matrix class 创建 Vector
实例可能会导致意外情况,例如 Vector
的 __init__()
方法未被调用(必须手动调用)。
不过,根据您的用例,最好保持干净并只使用 factory 创建实例:
class Matrix:
def __init__(self, nrows, ncols):
self.nrows = nrows
self.ncols = ncols
def __repr__(self):
return '{}(nrows={}, ncols={})'.format(
self.__class__.__name__, self.nrows, self.ncols)
class Vector(Matrix):
pass
def make_matrix(nrows, ncols):
if nrows == 1:
return Vector(nrows, ncols)
return Matrix(nrows, ncols)
演示:
>>> make_matrix(1, 5)
Vector(nrows=1, ncols=5)
>>> make_matrix(2, 5)
Matrix(nrows=2, ncols=5)
当然 make_matrix()
也可以作为 Matrix
class 的 (class/static) 方法来实现,但这会使父 class与其子 classes...
之一更紧密地耦合
我正在为我在 Python 中编写的项目使用矩阵。我知道已经有很多用于处理矩阵的库,但我正在编写自己的库,所以我确切地知道引擎盖下发生了什么。
所以我有一个 Matrix
基础 class 和一个 Vector
子 class。两者都按预期单独工作,但如果用单行或单列初始化,我希望 Matrix
成为 Vector
。
当 Matrix
以正确的大小初始化时,我尝试了类似 self = Vector(...)
的方法。但这似乎并不影响对象。我也想过调用 Vector
class 的 __init__()
方法,但这还不够,因为我最想要的是 Vector
的方法。
是否有处理这种情况的 pythonic 方式?
这是可以做到的,尽管这可能不是最好的方法。毕竟如果 Matrix
class 被实例化,人们期望结果是一个 Matrix
实例。
实现这一点的一种方法是自定义 Matrix
class:
class Matrix:
def __new__(cls, nrows, ncols):
if nrows == 1:
inst = super(Matrix, cls).__new__(Vector)
else:
inst = super(Matrix, cls).__new__(cls)
inst.nrows = nrows
inst.ncols = ncols
return inst
def __repr__(self):
return '{}(nrows={}, ncols={})'.format(
self.__class__.__name__, self.nrows, self.ncols)
演示:
>>> m1 = Matrix(2, 5)
Matrix(nrows=2, ncols=5)
>>> Matrix(1, 5)
Vector(nrows=1, ncols=5)
请注意,实例实际上是在 __new__()
方法中创建的,而 __init__()
用于初始化新创建的实例。
此外,正如 @Blckknght 在下面的评论中提到的,通过 Matrix class 创建 Vector
实例可能会导致意外情况,例如 Vector
的 __init__()
方法未被调用(必须手动调用)。
不过,根据您的用例,最好保持干净并只使用 factory 创建实例:
class Matrix:
def __init__(self, nrows, ncols):
self.nrows = nrows
self.ncols = ncols
def __repr__(self):
return '{}(nrows={}, ncols={})'.format(
self.__class__.__name__, self.nrows, self.ncols)
class Vector(Matrix):
pass
def make_matrix(nrows, ncols):
if nrows == 1:
return Vector(nrows, ncols)
return Matrix(nrows, ncols)
演示:
>>> make_matrix(1, 5)
Vector(nrows=1, ncols=5)
>>> make_matrix(2, 5)
Matrix(nrows=2, ncols=5)
当然 make_matrix()
也可以作为 Matrix
class 的 (class/static) 方法来实现,但这会使父 class与其子 classes...