根据父 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...

之一更紧密地耦合