2016-07-29 20 views
5

Ich weiß, es ist eine ähnliche Frage bereits gestellt, aber beantwortet nicht, was ich brauche, wie meins ist ein wenig anders.Return mit Argument innerhalb Generator

Mein Code:

def tFileRead(fileName, JSON=False): 
    with open(fileName) as f: 
     if JSON: 
      return json.load(f) 
     for line in f: 
      yield line.rstrip('\n') 

Was ich tun möchte: wenn JSON wahr ist, bedeutet seine Lesung aus einer JSON-Datei und ich möchte json.load(f) zurückkehren, sonst möchte ich die Zeilen erhalten die Datei in einen Generator.

Ich habe die Alternative der Umwandlung des Generators in json versucht, aber das wurde sehr chaotisch, sehr schnell, und funktioniert nicht sehr gut.

+0

Wenn kein JSON versucht, einen Abschluss zurückzugeben, der ein Generator – Aaron

+1

ist, muss eine einzelne Funktion entweder zurückgeben oder liefern. nicht beide – Aaron

+1

Sie könnten 'json.load' ergeben, aber dies wird nur die Schlüssel aus dem Diktat ergeben. Wie planen Sie, die Funktion in beiden Fällen zu verwenden? –

Antwort

2

Die erste Lösung, die mir in den Sinn kam, war, ein Generatorobjekt explizit zurückzugeben, das genau das Verhalten liefern würde, das Sie erreichen wollten.

Das Problem ist: Wenn Sie ein Generator-Objekt wie dieses return (line.rstrip('\n') for line in f) explizit zurückgegeben haben, wurde die Datei nach der Rückgabe geschlossen und jede weitere Lesung aus der Datei würde eine Ausnahme auslösen.

Sie sollten hier zwei Funktionen schreiben: eine, die eine JSON-Datei liest und eine für die normale Datei. Dann können Sie einen Wrapper schreiben, der über ein Argument entscheidet, welche dieser beiden Funktionen aufgerufen werden soll.

Oder nur die Iteration Teil wie diese in eine andere Funktion bewegen:

def iterate_file(file_name): 
    with open(file_name) as fin: 
     for line in fin: 
      yield line.rstrip("\n") 


def file_read(file_name, as_json=False): 
    if as_json: 
     with open(file_name) as fin: 
      return json.load(fin) 
    else: 
     return iterate_file(file_name) 
+0

Warum redest du über das Problem von etwas, was sie nicht tun? –

+0

@StefanPochmann du hast Recht. Mir fehlt hier ein Schritt. Ich dachte, du könntest es so machen ... aber warte, nein, das geht nicht. Deshalb habe ich es erwähnt. – Wombatz

1

Sie könnten das Wörterbuch yield from mit JSON geladen, also im dict über den Schlüssel-Wert-Paare laufen, aber das wäre nicht dein gewünschtes Verhalten.

def tFileRead(fileName, JSON=False): 
    with open(fileName) as f: 
     if JSON: 
      yield from json.load(f).items() # works, but differently 
     for line in f: 
      yield line.rstrip('\n') 

Es wäre schön, wenn Sie nur einen Generator zurückkehren können, aber das wird nicht funktionieren, da with verwenden, wird die Datei, sobald die Funktion zurückkehrt geschlossen, das heißt, bevor der Generator verbraucht wird.

def tFileRead(fileName, JSON=False): 
    with open(fileName) as f: 
     if JSON: 
      return json.load(f) 
     else: 
      return (line.rstrip('\n') for line in f) # won't work 

Alternativ können Sie eine andere Funktion definieren nur die Zeilen aus der Datei zur Gewinnung und verwenden, die im Generator:

def tFileRead(fileName, JSON=False): 
    if JSON: 
     with open(fileName) as f: 
      return json.load(f) 
    else: 
     def withopen(fileName): 
      with open(fileName) as f: 
       yield from f 
     return (line.rstrip('\n') for line in withopen(fileName)) 

Aber wenn Sie dort sind, können Sie auch wirklich nutzen nur zwei separate Funktionen zum Lesen der Datei en-Block als JSON oder zum Iterieren der Zeilen ...

+0

Woher wissen Sie, dass JSON in ein Dict geladen wird, nicht in eine Liste? Außerdem finde ich * "wenn du nur einen Generator zurückgeben könntest" * irreführend, wie du ** einen Generator zurückbringst (in deiner ersten Version). –

+0

@StefanPochmann Über das Diktat: Du hast Recht, hast nicht daran gedacht, dass JSON z. eine Liste. Über die Rückgabe eines Generators: Ich wollte mit "Return" zurückkehren, wie im zweiten Ansatz. –