Чому генератори і функції python поділяють ключове слово "def"?


10

Розглянемо наступне:

def some_function():
    return 1

def some_generator():
    yield 1

У наведеному вище коді some_functionє функцією, в той час some_generatorяк генератором. Вони виглядають досить схоже.

Проблема, яку я маю при читанні коду, полягає в тому, що мені потрібно переглядати кожен рядок у "функції", шукаючи yieldключове слово, перш ніж я зможу визначити, чи це насправді функція чи генератор!

Мені просто здається, що використання іншого ключового слова для генераторів мало б більше сенсу, наприклад:

gen some_generator():
    yield 1

Які переваги використання defключового слова як для генераторів, так і для функцій? Чому нове ключове слово не було введено для окремих функцій та генераторів?


Я не знаю реальної відповіді, але я часто починаю писати функції, які повертають списки, а потім перетворюються на генератори, коли це здається правильним. Наявність синтаксису робить це більш природним.
Gort the Robot

2
Пропозиція @StevenBurnap Дерека використовувати щось на зразок genзамість цього defне зробить цю трансформацію значно обтяжливішою.
jamesdlin

2
Взагалі мовні дизайнери зазвичай намагаються уникати додавання зайвих ключових слів. Кожне ключове слово, яке вони додають, є ідентифікатором, який програмам заборонено використовувати для інших цілей.
jamesdlin

@jamesdlin: Але питання стверджує, що нове ключове слово буде необхідним .
Джорджіо

1
@jamesdlin: Звичайно, ви можете розрізнити функції та генератори, переглянувши їх тіло, але питання стверджує, що використання різних ключових слів зробить код більш читабельним.
Джорджіо

Відповіді:


14

"Які переваги використання ключового слова def як для генераторів, так і для функцій?"

Хоча вони механічно відрізняються, але на практиці, коли я їх використовую, вони часто фактично однакові для мене концептуально (я не думаю, що багато дзвонють range()проти xrange()).

З точки зору розуміння того, що ця функція відбувається швидко, я погоджуюся, що щось втрачається з використанням def, але все не повинно бути занадто затуманеним у межах функції.

Навіть неявна return Noneситуація може заплутати передбачувану поведінку функції після довгих умовних умов (як, наприклад, було return Noneзадумане як остаточне поведінку або недогляд у логіці). Але це лише мої переконання з цього приводу.

Я не вважаю, що мій аргумент є особливо переконливим, хоча я просто відкладусь до PEP 255 :

Проблема: Введіть ще одне нове ключове слово (скажімо, "gen" або "генератор") замість "def" або іншим чином змініть синтаксис, щоб відрізнити функції генератора від негенераторних функцій.

Con: На практиці (як ви про них думаєте) генератори - це функції, але з поворотом, що вони відновлені. Механіка їх налаштування є порівняно незначною технічною проблемою, і введення нового ключового слова непомітно переосмислить механіку того, як запускаються генератори (життєво важлива, але крихітна частина життя генератора).

Про: Насправді (як ви про них думаєте) генератор-функції - це фактично фабричні функції, які виробляють генератор-ітератори як би за допомогою магії. У цьому відношенні вони докорінно відрізняються від негенераторних функцій, діючий більше як конструктор, ніж функція, тому повторне використання "def" в кращому випадку заплутане. Заява «урожайності», похована в тілі, недостатньо попереджає, що семантика настільки різна.

BDFL: "def" залишається. Жоден аргумент з обох сторін не є абсолютно переконливим, тому я порадився з інтуїцією мого дизайнера мови. Це говорить мені, що синтаксис, запропонований у PEP, є абсолютно правильним - не надто гарячим, не надто холодним. Але, як і Oracle у Delphi в грецькій міфології, воно не говорить мені чому, тому я не маю спростування аргументів проти синтаксису PEP. Найкраще, що я можу придумати (крім згоди з спростуванням ... вже зробленими), це "FUD". Якби це було частиною мови з першого дня, я дуже сумніваюся, що це зробило б сторінку Ендрю Кучлінга "Бородавки Пітона".


1
Варто зазначити, що нові await(та async withі async for) синтаксичні конструкції, додані в PEP 492 , які працюють дуже схоже на yield from, вимагають оголосити функцію, яку вони використовують, async defа не справедливу def.
Feuermurmel

2
  1. Додавання нових ключових слів ризикує порушити існуючі програми. Мовні дизайнери, як правило, намагаються уникати додавання нових ключових слів, особливо для мовних функцій, доданих після того, як мова вже набула деякої популярності. Кожне ключове слово, яке вони додають, - це ідентифікатор, який програмам заборонено використовувати для інших цілей, тому додавання ключового слова може потенційно зламати існуючі програми. Мовні дизайнери повинні зважити переваги нового ключового слова та витрат.

  2. Сумніваюся, що визначення окремого ключового слова для генераторів принесло б велику користь. Щоб зрозуміти, чи відповідає символ імені функції або імені генератора, те, що має значення для абонентів, і абоненти не повинні (а іноді і не можуть) дивитись, яке ключове слово було використано для його реалізації. Це відповідальність за краще називати конвенції та документацію.


1

Генератори - це функції, які оцінюють ліниво. Зважаючи на те, що вони однакові в основі, є сенс, що вони будуть використовувати одне і те ж ключове слово. Одним із варіантів може бути використання коментаря для визначення того, що є для даного примірника:

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

def some_generator(): #This is a generator.
    yield 1

0

Я б припустив, що це тому, що це більше піфонічне, але що я знаю? ;)

Я не думаю, що це так важливо. Мені простіше запам'ятати, бо не потрібно запам’ятовувати їх обох.

EDIT: PEP може сказати, що ви можете там розслідувати.


Дякую! Насправді, PEP говорить! Див. PEP-255 про плюси та мінуси та остаточне рішення щодо нового ключового слова для генераторів.
Дерек Квок

З піфонічним значенням: "Так, як це робиться в Python"?
Джорджіо
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.