2017-12-26 3 views
1

Ich arbeite mit Matrizen für ein Projekt, das ich in Python schreibe. Ich weiß, dass bereits viele Bibliotheken existieren, um Matrizen zu manipulieren, aber ich schreibe meine eigenen, damit ich genau weiß, was unter der Haube passiert.Initialisieren einer Unterklasse auf Bedingung von der Elternklasseninitialisierung

Also habe ich eine Matrix Basisklasse und eine Vector Unterklasse. Beide funktionieren wie erwartet einzeln, aber ich möchte eine Matrix als Vector haben, wenn sie mit einer einzelnen Zeile oder Spalte initialisiert wird.

Ich versuchte etwas wie self = Vector(...), wenn die Matrix mit der richtigen Größe initialisiert wird. Aber das scheint das Objekt nicht zu beeinflussen. Ich dachte auch an die __init__() Methode der Vector Klasse, aber das reicht nicht, denn was ich am wichtigsten möchte, sind die Vector Methoden.

Gibt es einen pythischen Umgang mit einer solchen Situation?

+0

Verwenden Sie eine Factory, die auf der Grundlage Ihrer Kriterien entscheidet, anstatt mit "__init__" etwas zu tun. –

Antwort

2

Dies kann getan werden, obwohl es möglicherweise nicht der beste Weg ist, es zu tun. Wenn schließlich die Klasse Matrix instanziiert wird, erwartet man, dass das Ergebnis eine Matrix Instanz ist.

Eine Möglichkeit, dies zu erreichen ist es, den Konstruktor der Matrix Klasse anpassen:

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) 

Demo:

>>> m1 = Matrix(2, 5)                                                                                 
Matrix(nrows=2, ncols=5)                                                                               
>>> Matrix(1, 5)                                                                                 
Vector(nrows=1, ncols=5) 

Geist, die Instanzen innerhalb der __new__() Methode tatsächlich erstellt werden, während __init__() verwendet wird zum Initialisieren der neu erstellten Instanz.

Auch, wie in einem Kommentar unterhalb von @Blckknght erwähnt, eine Vector Instanz durch die Matrix-Klasse zu schaffen, um unerwünschte Überraschungen führen kann, wie wie die Vector ‚s __init__() Methoden nicht aufgerufen zu werden (es wäre manuell aufgerufen werden) .

Je nach Anwendungsfall, aber es könnte also besser sein, die Dinge sauber zu halten und nur eine Fabrik zum Beispiel Erstellung verwenden:

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) 

Demo:

>>> make_matrix(1, 5) 
Vector(nrows=1, ncols=5) 
>>> make_matrix(2, 5) 
Matrix(nrows=2, ncols=5) 

Natürlich make_matrix() könnte auch als eine (Klasse/statische) Methode der Matrix Klasse implementiert werden, aber das würde die Elternklasse enger mit einer seiner Kindklassen gekoppelt ...

+0

Eine Warnung zur Verwendung von '__new__' in dieser Situation: Die Methode' __init__' einer Klasse wird nur aufgerufen, wenn ihre Instanz wird durch einen Aufruf seiner eigenen Klasse erstellt. Wenn Sie eine Instanz von "Vector" erstellen, indem Sie "Vector .__ new__" aus "Matrix .__ new__" aufrufen, wird keine "__init__" -Methode aufgerufen. Der Versuch, 'Vector' direkt zu nennen, führt zu einer unendlichen Rekursion (da' Vector' 'Matrix .__neu__' erbt, wenn Sie es nicht überschreiben). – Blckknght

+0

Dies ist eine gültige Bemerkung und ein weiterer Grund dafür, das nicht zu empfehlen, ich würde lieber mit einer Fabrik gehen. Danke für das Erwähnen. – plamut

+0

Vielen Dank! Ich hatte diese "__new__" Methode nie gesehen. Ich werde versuchen, beide Methoden zu sehen, die am besten geeignet ist.Ich denke, Ihre Werkslösung ist die pythischste und natürlichste Lösung. –

Verwandte Themen