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



我正在与矩阵合作,为我在python写的项目。我知道许多图书馆已经存在用于操纵矩阵,但我正在写自己的矩阵,所以我确切地知道引擎盖下发生了什么。

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

我尝试了self = Vector(...)之类的东西,当时Matrix的大小初始化。但这似乎不会影响对象。我还想到调用Vector类的__init__()方法,但这还不够,因为我最重要的是Vector的方法。

是否有一种处理这种情况的Pythonic方法?

这可以做到,尽管这可能不是这样做的最佳方法。毕竟,如果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下面的评论中提到的那样,通过矩阵类创建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类的(类/静态)方法实现,但这将使父级与其子类之一相结合...

最新更新