2016-07-29 15 views
5

Wiem, że jest podobne pytanie już zadane, ale nie odpowiada na to, czego potrzebuję, ponieważ moje jest trochę inne.Powrót z argumentem wewnątrz generatora

Mój kod:

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

Co chcę zrobić: jeśli JSON jest prawdziwe, oznacza to jej odczyt z pliku json i chcę wrócić json.load(f), w przeciwnym razie, chcę uzyskując linie plik do generatora.

Próbowałem alternatywy zamiany generatora w json, ale to stało się bardzo niechlujne, bardzo szybkie i nie działa zbyt dobrze.

+0

jeśli nie JSON spróbuj zwrócić zamknięcie, które jest generatorem – Aaron

+1

, pojedyncza funkcja musi albo powrócić, albo ulec. nie oba: – Aaron

+1

Możesz "zrezygnować z json.load", ale to tylko wyda klucze z dyktatury. Jak zamierzasz korzystać z tej funkcji w obu przypadkach? –

Odpowiedz

2

Pierwsze rozwiązanie, które przyszło mi do głowy, to jednoznaczne zwrócenie obiektu generatora, który zapewni dokładne zachowanie, które próbowałeś osiągnąć.

Problem polega na tym, że jeśli jawnie zwrócono obiekt generatora, taki jak ten return (line.rstrip('\n') for line in f), plik zostanie zamknięty po powrocie i jakiekolwiek dalsze czytanie z pliku spowoduje zgłoszenie wyjątku.

Powinieneś napisać tutaj dwie funkcje: jedną, która czyta plik json, a druga plik normalny. Następnie możesz napisać wrapper, który desides na argumencie, który z tych dwóch funkcji wywoła.

Albo po prostu przesunąć część iteracji do innej funkcji takich jak to:

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

Dlaczego mówisz o problemie czegoś, czego nie robią? –

+0

@StefanPochmann masz rację. Brakuje mi tutaj kroku. Myślałem, że możesz to zrobić w ten sposób ... ale czekaj, nie, to nie działa. Dlatego wspominałem o tym. – Wombatz

1

Mogłeś yield from słownika ładowane z JSON, co iteracja ciągu klucz-wartość par w dict, ale nie byłoby to pożądane zachowanie.

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') 

Byłoby miło, gdyby można było po prostu wrócić do generatora, ale to nie będzie działać, ponieważ używając with, plik jest zamknięty, jak tylko wróci funkcyjnych, to znaczy zanim generator jest zużywana.

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 

Alternatywnie, można określić inną funkcję tylko do otrzymania linii z pliku i użyć jej w generatorze:

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)) 

Ale kiedy jesteś tam, można naprawdę wykorzystać dwie odrębne funkcje do odczytu pliku en-block jako JSON lub do iterowania linii ...

+0

Skąd wiesz, że JSON ładuje się do dyktatury, a nie listy? Ponadto znajduję * "jeśli mógłbyś tylko zwrócić generator" * wprowadzając w błąd, ponieważ ** zwracasz generator (w swojej pierwszej wersji). –

+0

@StefanPochmann Informacje o dykcie: Masz rację, nie myślałeś o zwrocie JSON, np. lista. O powrocie generatora: chciałem powrócić z 'return', tak jak w drugim podejściu. –

Powiązane problemy