2017-06-18 2 views
4

Ich habe eine Klasse, die wenige statische Felder hat und von iterable initialisiert wird (wie Ausgabe von csvreader). Die __init__ führt Typumwandlung von Strings in Zahlen für einige von ihnen:Typ Umwandlung für namedtuple Felder während der Initialisierung

class PerformanceTestResult(object): 
    def __init__(self, csv_row): 
     # csv_row[0] is just an ordinal number of the test - skip that 
     self.name = csv_row[1]   # Name of the performance test 
     self.samples = int(csv_row[2]) # Number of measurement samples taken 
     self.min = int(csv_row[3])  # Minimum runtime (ms) 
     self.max = int(csv_row[4])  # Maximum runtime (ms) 
     self.mean = int(csv_row[5])  # Mean (average) runtime (ms) 
     self.sd = float(csv_row[6])  # Standard deviation (ms) 

Ich denke darüber Umwandlung nur ein namedtuple zu sein, da es sonst nicht viel zu ihm. Aber ich möchte die Typumwandlung während der Initialisierung beibehalten. Gibt es eine Möglichkeit, dies mit namedtuple zu tun? (Ich habe nicht __init__ Methode in der ausführlichen Ausgabe von namedtuple Factory-Methode bemerkt, die ich initializer Arbeiten pausieren, wie die Standard gibt.)

+0

Haben Sie ein Beispiel dafür, wie Ihr namedtuple aussehen soll? – user1767754

Antwort

0

Statt in den csv_row zugeben, wie sie ist, wie Sie gerade tun, könnten Sie entpacken Sie es mit dem Entpacker *. Zum Beispiel:

>>> def f(a, b): 
...  return a + b 
... 
>>> csv_row = [1, 2] 
>>> f(*csv_row) # Instead of your current f(csv_row) 

Dies würde auch mit namedtuple, arbeitet, da die Reihenfolge der Argumente beim Auspacken gehalten werden:

>>> from collections import namedtuple 
>>> PerformanceTestResult = namedtuple('PerformanceTestResult', [ 
...  'name', 
...  'samples', 
...  'min', 
...  'max', 
...  'mean', 
...  'sd', 
... ]) 
>>> test_row = ['test', '123', 2, 5, 3, None] # from your csv file 
>>> ptr = PerformanceTestResult(*test_row) 
>>> ptr 
PerformanceTestResult(name='test', samples='123', min=2, max=5, mean=3, sd=None) 

Nicht nur das Sie erlaubt namedtuple, zu verwenden, die wie ein wirklich scheinen gute Idee hier, aber es beseitigt auch die Notwendigkeit für Ihre PerformanceTestResult etwas über die CSV-Datei wissen! Abstraktion ist gut, da Sie jetzt dieselbe Klasse verwenden können, unabhängig davon, woher die Daten stammen und in welchem ​​Format.


Wenn Sie die int() und float() Konvertierungen benötigen, du wirst haben eine eigene Konvertierungsfunktion zu schreiben. Sie können entweder in die PerformanceTestResult von Subklassifizieren bauen:

>>> ptr = PerformanceTestResult.from_csv(your_csv_row) 

Oder Sie können eine separate Konvertierungsfunktion erstellen:

def parse_csv_row(row): 
    return (row[0], int(row[1]), ...) 

Und jetzt

_PerformanceTestResult = namedtuple('PerformanceTestResult', [...]) 

class PerformanceTestResult(_PerformanceTestResult): 
    @classmethod 
    def from_csv(cls, row): 
     return cls(
      row[0], 
      int(row[1]), 
      int(row[2]), 
      int(row[3]), 
      int(row[4]), 
      int(row[5]), 
      float(row[6]) 
     ) 

Welche kann wie so verwendet werden, Verwenden Sie dies, um die Zeile vor dem Entpacken zu konvertieren:

>>> ptr = PerformanceTestResult(*parse_csv_row(your_csv_row))