Seite 2 von 2
Re: Klasse zum auslesen einer Datei
Verfasst: Samstag 28. Januar 2017, 22:09
von Sirius3
@Ambriador: jetzt fängst Du solangsam an, die richtigen Fragen stellen. Es ist ein Fehler, dass das Table-Objekt keine Attribute titles und cols hat. Du mußt dafür sorgen, dass diese Attribute in »__init__« angelegt werden. Eigentlich sollte man nicht nur durch Zufall merken, dass die Funktion nicht das macht, was man eigentlich denkt, was sie macht (obwohl ich das heute schon um 18:13Uhr und BlackJack um 19:18Uhr geschrieben haben). Sondern man schreibt Tests, die das auch überprüfen.
Re: Klasse zum auslesen einer Datei
Verfasst: Samstag 28. Januar 2017, 23:22
von Ambriador
@Sirius3 wie gesagt, einzeln hatte meine Funktion funktioniert, ich dachte ich muss sie dann einfach nur noch aufrufen und fertig, aus euren Kommentaren ist mir das erst nicht so schlüssig geworden. Dann versuche ich mal in der Nachtschicht was zu basteln.
Re: Klasse zum auslesen einer Datei
Verfasst: Sonntag 29. Januar 2017, 00:15
von Ambriador
Also wenn ich das richtig verstanden habe darf ich in der "__init__" nicht unterscheide mit einem "if/else" sondern muss ein objekt erstellen, aber wie lasse ich die "__init__" denn erkennen ob es sich um ein file oder attribute handelt?
Re: Klasse zum auslesen einer Datei
Verfasst: Sonntag 29. Januar 2017, 00:23
von BlackJack
@Ambriador: Doch, Du musst in der `__init__()` testen und entscheiden was von beiden der Benutzer angegeben hat und was daraufhin passieren muss. Aber egal was der Aufrufer übergibt, *nachdem* die `__init__()` ausgeführt wurde und zum Aufrufer zurück kehrt muss das Objekt in einem benutzbaren Zustand sein. Das heisst die Attribute `headers` und `cols` *dieses* Objekts müssen die entsprechenden Daten enthalten.
Re: Klasse zum auslesen einer Datei
Verfasst: Sonntag 29. Januar 2017, 00:26
von Ambriador
Oh je ok, und wofür brauche ich dann die parse_csv? Hört sich so an als ob der Code zum bereitstellen ja schon in die "__init__" muss?
EDIT:
Sorry ist schon spät. Ich denke mal das es so ungefähr aussehen soll?
Code: Alles auswählen
import csv
class Table:
def __init__(self, titles=None, cols=None, filename = None):
if filename is None:
self.titles = titles
self.cols = cols
self.filename = filename
else:
self.file1 = self.parse_csv(filename)
def __str__(self):
return (str(self.titles) +', '+ str(self.cols))
def __eq__(self, other):
return (self.titles, self.cols) == (other.titles, other.cols)
def parse_csv(self, filename):
with open(filename) as f:
reader = csv.reader(f)
header = next(reader)
cols = list(zip(*reader))
return [header, cols]
Jetzt sagt er mir aber "global name "open" is not definded", obwohl das doch zur csv gehört?
Re: Klasse zum auslesen einer Datei
Verfasst: Sonntag 29. Januar 2017, 06:16
von Ambriador
Endlich habe ich was halbwegs vernünftiges:
Code: Alles auswählen
import csv
class Table:
def __init__(self, titles=None, cols=None, filename = None):
if filename is None:
self.titles = titles
self.cols = cols
self.filename = filename
else:
self.file1 = self.parse_csv(filename)
def __str__(self):
return (str(self.titles) +', '+ str(self.cols))
def __eq__(self, other):
return (self.titles, self.cols) == (other.titles, other.cols)
def parse_csv(self, filename):
with open(filename) as f:
reader = csv.reader(f)
self.titles = next(reader)
self.cols = list(zip(*reader))
return [self.titles, self.cols]
Jetzt gibt er mir nur noch die "self.cols" als string und nicht als float aus.
Re: Klasse zum auslesen einer Datei
Verfasst: Sonntag 29. Januar 2017, 10:44
von Sirius3
@Ambriador: das sieht doch jetzt schon mal gut aus. Und es fehlen nur noch ein paar Kleinigkeiten. Achte auf die korrekte Einrückung: 4 Leerzeichen pro Ebene. Setze immer alle Attribute in »__init__«. Für was ist »file1« da? Warum werden »titles« und »cols« nicht immer gesetzt? Für eine klare Schnittstelle sollte eine Methode entweder den internen Zustand eines Objektes ändern, oder etwas zurückliefern, aber nicht beides.
Re: Klasse zum auslesen einer Datei
Verfasst: Sonntag 29. Januar 2017, 14:00
von Ambriador
Vielen Vielen Dank für eure Hilfe, ich hab es endlich hinbekommen
Code: Alles auswählen
import csv
class Table:
def __init__(self, titles=None, cols=None, filename = None):
if filename is None:
self.titles = titles
self.cols = cols
self.filename = filename
else:
self.titles = []
self.cols = []
self.filename = self.parse_csv(filename)
def __str__(self):
return (str(self.titles) +', '+ str(self.cols))
def __eq__(self, other):
return (self.titles, self.cols) == (other.titles, other.cols)
def parse_csv(self, filename):
with open(filename) as f:
reader = csv.reader(f)
self.titles = next(reader)
self.cols = [list(a) for a in zip(*reader)]
self.cols = [[float(b) for b in c] for c in self.cols]
return [self.titles, self.cols]
Re: Klasse zum auslesen einer Datei
Verfasst: Sonntag 29. Januar 2017, 14:34
von Sirius3
@Ambriador: nein, hast Du nicht. Was Du an das Attribut »filename« bindest ist kein Dateiname.
Daneben liefert »parse_csv« etwas zurück und ändert Attribute. Das sollte nicht sein. Zeile 26 könnte man sich auch sparen. Außerdem solltest Du erklären können, was »zip(*reader)« genau macht, nicht dass Dein Lehrer auf die Idee kommt, Du könntest das irgendwo abgeschrieben haben.
Code: Alles auswählen
import csv
class Table:
def __init__(self, titles=None, cols=None, filename=None):
self.titles = titles
self.cols = cols
if filename is not None:
self.parse_csv(filename)
def __str__(self):
return "{}, {}".format(self.titles, self.cols)
def __eq__(self, other):
return self.titles == other.titles and self.cols == other.cols
def parse_csv(self, filename):
with open(filename) as f:
reader = csv.reader(f)
self.titles = next(reader)
self.cols = [[float(b) for b in c] for c in zip(*reader)]
Re: Klasse zum auslesen einer Datei
Verfasst: Montag 30. Januar 2017, 19:41
von Ambriador
AH ok ,war mir nicht klar das man das auch so machen kann.
Wieso ist es nicht so gut wenn parse_csv etwas zurück gibt?
Re: Klasse zum auslesen einer Datei
Verfasst: Montag 30. Januar 2017, 20:13
von Sirius3
@Ambriador: eine Methode sollte genau eine Sache machen. Z.B. entweder etwas Setzen, oder einen Wert zurückliefern. Macht sie beides, verwirrt das nur, wie Dich z.B., da Du Dich ja gezwungen gefühlt hast, den Rückgabewert an irgendetwas (self.filename) zu binden, was so gar keinen Sinn gemacht hat.
Re: Klasse zum auslesen einer Datei
Verfasst: Dienstag 31. Januar 2017, 09:56
von BlackJack
Damit die API nicht so stehen bleibt, hier mal ein Beispiel wie so eine Klasse eher aussehen sollte:
Code: Alles auswählen
#!/usr/bin/env python
# coding: utf8
from __future__ import absolute_import, division, print_function
import csv
import io
from itertools import izip
CSV_SOURCE = '''\
Zeit,Temperatur
0,15.2
3,16.1
6,14.8
9,20.2
'''
class Table(object):
def __init__(self, headers, columns):
self.headers = headers
self.columns = columns
def __repr__(self):
return '{0.__class__.__name__}({0.headers!r}, {0.columns!r})'.format(
self
)
def __eq__(self, other):
try:
return (
(self.headers, self.columns) == (other.headers, other.columns)
)
except AttributeError:
return NotImplemented
def __ne__(self, other):
return not self == other
def __hash__(self):
return TypeError('unhashable type: ' + self.__class__.__name__)
@classmethod
def read_csv(cls, csv_file):
reader = csv.reader(csv_file)
headers = next(reader)
columns = [map(float, row) for row in izip(*reader)]
return cls(headers, columns)
@classmethod
def load_csv(cls, filename):
with open(filename) as csv_file:
return cls.read_csv(csv_file)
def main():
table_a = Table(
['Zeit', 'Temperatur'], [[0.0, 3.0, 6.0, 9.0], [15.2, 16.1, 14.8, 20.2]]
)
table_b = Table.read_csv(io.BytesIO(CSV_SOURCE))
table_c = Table.load_csv('test.csv')
print(table_a)
print(table_b)
print(table_c)
print(table_a == table_b == table_c)
if __name__ == '__main__':
main()