Python-hjälp! (klasser/objekt/attribut/läsa in från fil)

Permalänk
Medlem

Python-hjälp! (klasser/objekt/attribut/läsa in från fil)

N/A

Permalänk

Jag ska försöka förklara så mycket som möjligt men ändå "tvinga" dig att göra lösningen själv. Läs på om funktionerna i Pythondokumentationen, som du kan lätt hitta om du googlar

För att göra det så enkelt som möjligt gör du en for loop som gör en loop per objekt. Insidan av loopen kan se ut ung så här:

obj = dinKlass() obj.tillverkare = f.readline() obj.modell = f.readline() ...

f är alltså din fil som du tidigare öppnat.

Du har ett par problem kvar gissar jag. Den ena är att många av attributen är i själva verket siffor, så du måste konvertera strängarna som readline läser in. Det andra är att readline lämnar en newline-karaktär i slutet, så du måste ta bort det sista tecknet (läs om string i dokumentationen och hur du kan ta bort tecken).
Det tredje är hur du avbryter loopen.

Ett trick man kan göra är att använda sig av en evig while-loop istället och istället avbryta med hjälp av Exceptions:

f=open('filnamn','r') try: while True: obj=DinKlass() ... Except IOError: pass #Gör inget här eftersom vi förväntar oss att få det här "felet" finally: f.close()

Om du inte stött på exceptions så kan man säga att om man stöter på något sådant, t.ex. försöker läsa en rad i en fil, fast man redan nått slutet, så "kastas" man ut ur koden. Man fångar Exceptions i ett try-block och utför en viss åtgärd. I fallet ovan fångar vi IOError, men gör inget åt det eftersom det indikerar filslut.
finally är något som görs för alla exceptions efter att man utfört åtgärder, även om man explicit inte fångar en viss typ.

Permalänk
Medlem

A thousand ways to skin a cat

Utan att ha några ambitioner att vara pedagogisk, så kan jag visa upp mitt fredagsnöje... att hitta några olika roliga sätt att lösa ditt problem.

# coding: latin-1 def printList(lst): for o in lst: print str(o) print # Testdata: data = """% Format: tillverkare / modell / pris / butik / lagerstatus / stad Nokia E71 3600 Elgiganten 15 Göteborg SonyEricsson W995 4200 Siba 40 Stockholm""" class Mobil: def __init__(self, tillverkare, modell, pris, butik, lagerstatus, stad): self.tillverkare = tillverkare self.modell = modell self.pris = pris self.butik = butik self.lagerstatus = lagerstatus self.stad = stad def __str__(self): return "%s %s, %s kr, %s %s, %s st" % (self.tillverkare, self.modell, self.pris, self.butik, self.stad, self.lagerstatus) allRows = data.split("\n") # Eller om du läser från fil: # f = open("text.txt") # allRows = f.readlines() # f.close() #################################################################### # Sätt 1: via index # Klipp bort första raden, den är ointressant. rows = allRows[1:] objects = [] i = 0 while i <= len(rows) - 6: # Klipp ut en dellista på 6 element från plats i till (inte t.o.m.) plats i+6: data = rows[i:i+6] # Packa upp dellistan i 6 variabler: tillv, mod, pris, butik, lager, stad = data # Lägg till en ny instans i listan: objects.append( Mobil(tillv, mod, pris, butik, lager, stad) ) i += 6 printList(objects) #################################################################### # Ett annat sätt, genom att korta ner rows för varje iteration i loopen: rows = allRows[1:] objects = [] while len(rows) >= 6: data, rows = rows[:6], rows[6:] # data är nu de 6 första, elementen, rows sätts till alla som kommer efter # de 6 första. tillv, mod, pris, butik, lager, stad = data objects.append( Mobil(tillv, mod, pris, butik, lager, stad) ) printList(objects) # Något av dessa ovanstående sätt skulle väl kunna rekommenderas. #################################################################### # Men sedan kan man ju skoja till det lite om man känner för det... # Jag lämnar det som övning att förstå vad som sker. ;-) # Ny mobilklass med annan konstruktor. class KulMobil: # init tar här en lista av tuplar, med attributets namn och dess värde. Ex.: # [("tillverkare", "Nokia"), ("modell", "E71"), ... ] def __init__(self, arglist): for a in arglist: name, value = a setattr(self, name, value) def __str__(self): return "%s %s, %s kr, %s %s, %s st" % (self.tillverkare, self.modell, self.pris, self.butik, self.stad, self.lagerstatus) attrNames = ["tillverkare", "modell", "pris", "butik", "lagerstatus", "stad"] rows = allRows[1:] objects = [] while len(rows) >= 6: data, rows = rows[:6], rows[6:] objects.append( KulMobil(zip(attrNames, data)) ) printList(objects) #################################################################### # Eller så kan man klippa ur attributnamnen ur formatbeskrivningen, # och göra på samma sätt. attrNames = [attr.split()[-1] for attr in allRows[0].split("/")] rows = allRows[1:] objects = [] while len(rows) >= 6: data, rows = rows[:6], rows[6:] objects.append( KulMobil(zip(attrNames, data)) ) printList(objects) #################################################################### # Och för att skoja till det ännu lite mer, så här på fredagkvällen: rows = allRows[1:] printList( [ KulMobil(zip(attrNames,rows[6*i:6*(i+1)])) for i in range(len(rows) / 6) ] ) #################################################################### # Ja vad tusan, definitionen av attrNames går ju att trycka in. Och rows behövs ju inte heller! # (Det är egentligen en enradare, uppdelad för att forumet inte ska sura.) printList( [ KulMobil(zip([attr.split()[-1] for attr in allRows[0].split("/")],allRows[1+6*i:1+6*(i+1)])) \ for i in range((len(allRows)-1) / 6) ] ) #################################################################### # ...och printList är ju en fuskig flerradare, såna vill vi inte ha! import sys map(sys.stdout.write, [ str(s) + "\n" for s in [ KulMobil(zip([attr.split()[-1] for attr in allRows[0].split("/")], \ allRows[1+6*i:1+6*(i+1)])) for i in range((len(allRows)-1) / 6) ] ] + ["\n"])

Ungefär sådär roligt kan man ha en kväll när man inte har något vettigt att göra.

Observera att de tre sista sätten inte rekommenderas.