Dlaczego generatory i funkcje Pythona współdzielą słowo kluczowe „def”?

10

Rozważ następujące:

def some_function():
    return 1

def some_generator():
    yield 1

W powyższym kodzie some_functionjest funkcja, podczas gdy some_generatorjest generatorem. Wyglądają dość podobnie.

Problem, który mam podczas odczytywania kodu, polega na tym, że muszę skanować każdą linię w „funkcji” w poszukiwaniu yieldsłowa kluczowego, zanim będę mógł ustalić, czy jest to faktycznie funkcja, czy generator!

Wydaje mi się po prostu, że użycie innego słowa kluczowego dla generatorów miałoby większy sens, np .:

gen some_generator():
    yield 1

Jakie są zalety używania defsłowa kluczowego w przypadku generatorów i funkcji? Dlaczego nowe słowo kluczowe nie zostało wprowadzone do oddzielnych funkcji i generatorów?

Derek Kwok
źródło
Nie znam prawdziwej odpowiedzi, ale często zaczynam pisać funkcje, które zwracają listy, a potem przekształcam się w generatory, kiedy wydaje się to właściwe. Dopasowywanie składni sprawia, że ​​jest to bardziej naturalne.
Gort the Robot
2
@StevenBurnap Sugestia Dereka, by użyć czegoś takiego genzamiast defnie spowodowałaby, że ta transformacja byłaby znacznie bardziej uciążliwa.
jamesdlin
2
Ogólnie rzecz biorąc, projektanci języków zwykle starają się unikać dodawania niepotrzebnych słów kluczowych. Każde dodane słowo kluczowe jest identyfikatorem, którego programy nie mogą wykorzystywać do innych celów.
jamesdlin
@jamesdlin: Ale pytanie brzmi, że konieczne byłoby nowe słowo kluczowe .
Giorgio
1
@jamesdlin: Oczywiście można odróżnić funkcje i generatory od ich ciała, ale pytanie dowodzi, że użycie różnych słów kluczowych sprawiłoby, że kod byłby bardziej czytelny.
Giorgio

Odpowiedzi:

14

„Jakie są zalety używania słowa kluczowego def zarówno dla generatorów, jak i funkcji?”

Chociaż są one mechanicznie różne, w praktyce, kiedy ich używam, często są dla mnie efektywnie takie same koncepcyjnie (nie myślę dużo o sprawdzaniu range()vs xrange()).

Jeśli chodzi o zrozumienie, o co chodzi w tej funkcji szybko, zgadzam się, że coś zostało utracone przy użyciu def, ale rzeczy nie powinny być zbyt zaciemnione w funkcji na początku.

Nawet domniemane return Nonemoże mylić zamierzone zachowanie funkcji po długim okresie warunkowym (jak w, było return Nonezamierzone jako zachowanie ostateczne lub niedopatrzenie w logice). Ale to tylko moje przekonania.

Nie wydaje mi się jednak, aby mój argument był szczególnie przekonujący, dlatego odłożę się na PEP 255 :

Problem: Wprowadź inne nowe słowo kluczowe (powiedzmy „gen” lub „generator”) zamiast „def” lub w inny sposób zmień składnię, aby odróżnić funkcje generatora od funkcji innych niż generator.

Przeciw: W praktyce (jak o nich myślisz) generatory funkcjami, ale z tym, że można je wznowić. Mechanika ich konfiguracji jest stosunkowo niewielkim problemem technicznym, a wprowadzenie nowego słowa kluczowego zbytnio podkreśliłoby mechanikę uruchamiania generatorów (istotna, ale niewielka część życia generatora).

Pro: W rzeczywistości (jak o nich myślisz), funkcje generatora są tak naprawdę funkcjami fabrycznymi, które wytwarzają iteratory generatora jak za pomocą magii. Pod tym względem radykalnie różnią się od funkcji innych niż generatory, zachowując się bardziej jak konstruktor niż funkcja, więc ponowne użycie „def” jest w najlepszym razie mylące. Wyrażenie „dochodowości” zakopane w ciele nie jest wystarczającym ostrzeżeniem, że semantyka jest tak inna.

BDFL: „def” pozostaje. Żaden argument po obu stronach nie jest całkowicie przekonujący, więc skonsultowałem się z intuicją mojego projektanta języka. Mówi mi, że składnia zaproponowana w PEP jest dokładnie właściwa - nie za gorąca, nie za zimna. Ale, podobnie jak Wyrocznia w Delfach w mitologii greckiej, nie mówi mi dlaczego, więc nie mam obalenia argumentów przeciwko składni PEP. Najlepsze, co mogę wymyślić (poza zgodzeniem się z obaleniami ... już zrobionymi) to „FUD”. Gdyby była to część języka od pierwszego dnia, bardzo wątpię, czy stworzyłaby stronę „Python Warts” Andrew Kuchlinga.

quaspas
źródło
1
Warto zauważyć, że nowe await(i async witha async for) konstrukcje składniowe dodane w PEP 492 , które pracują bardzo podobny do yield from, wymagają funkcji są one wykorzystywane w celu być zadeklarowane używając async defzamiast po prostu def.
Feuermurmel,
2
  1. Dodanie nowych słów kluczowych grozi zerwaniem istniejących programów. Projektanci języków zwykle starają się unikać dodawania nowych słów kluczowych, szczególnie w przypadku funkcji językowych dodanych po tym, jak język zyskał już na popularności. Każde dodane słowo kluczowe jest identyfikatorem, którego programy nie mogą wykorzystywać do innych celów, więc dodanie słowa kluczowego może potencjalnie uszkodzić istniejące programy. Projektanci języków muszą porównać zalety nowego słowa kluczowego z kosztami.

  2. Wątpię, aby zdefiniowanie osobnego słowa kluczowego dla generatorów przyniosło wiele korzyści. Zrozumienie, czy symbol odpowiada nazwie funkcji, czy nazwie generatora, jest ważne dla dzwoniących, a dzwoniący nie powinni (a czasem nie mogą) patrzeć na to, jakie słowo kluczowe zostało użyte do jego zaimplementowania. Odpowiedzialność za lepsze konwencje nazewnictwa i dokumentację.

jamesdlin
źródło
1

Generatory to funkcje leniwie oceniające. Biorąc pod uwagę, że u podstaw są to samo, sensowne byłoby, gdyby użyli tego samego słowa kluczowego. Jedną z opcji może być użycie komentarza w celu ustalenia, który z nich dla danego wystąpienia:

def some_function(): #This is a function.
    return 1

def some_generator(): #This is a generator.
    yield 1
Inżynier świata
źródło
0

Sądzę, że to dlatego, że jest bardziej Pythonic, ale co ja wiem? ;)

Nie sądzę, żeby to miało tak duże znaczenie. Łatwiej mi je zapamiętać, ponieważ nie trzeba ich zapamiętywać.

EDYCJA: PEP może powiedzieć, że możesz to zbadać.

XiKuuKy
źródło
Dzięki! W rzeczywistości PEP mówi! Zobacz PEP-255, aby zobaczyć zalety / wady i ostateczną decyzję dotyczącą nowego słowa kluczowego dla generatorów.
Derek Kwok
Ze znaczeniem Python: „Jak to się robi w Pythonie”?
Giorgio