在父类初始化的条件下初始化子类

时间:2017-12-26 21:59:34

标签: python matrix subclass

我正在使用矩阵来处理我用Python编写的项目。我知道很多图书馆已经存在用于操纵矩阵但是我自己编写了这些库,所以我确切地知道幕后发生了什么。

所以我有一个Matrix基类和一个Vector子类。两者都按预期单独工作,但如果使用单行或列进行初始化,我希望Matrix成为Vector

self = Vector(...)初始化为正确的大小时,我尝试了Matrix之类的内容。但这似乎并没有影响到对象。我还想过调用__init__()类的Vector方法,但这还不够,因为我最重要的是Vector方法。

是否有处理这种情况的pythonic方式?

1 个答案:

答案 0 :(得分:2)

这可以做到,虽然它可能不是最好的方法。毕竟,如果Matrix类被实例化,那么期望结果是Matrix实例。

实现这一目标的一种方法是自定义Matrix类的构造函数:

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类创建Vector实例可能会导致意外的意外,例如Vector的{​​{1}没有被调用的方法(必须手动调用)。

根据您的使用情况,最好保持清洁,只需使用 factory 进行实例创建:

__init__()

演示:

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()类的(类/静态)方法实现,但这会使父类与其子类之一更紧密地耦合......