Простой пример Два метода, один вызывается из другого:
def method_a(arg):
some_data = method_b(arg)
def method_b(arg):
return some_data
В Python мы можем объявить def
внутри другого def
. Так что, если method_b
требуется и вызывается только из method_a
, я должен объявить method_b
внутри method_a
? как это :
def method_a(arg):
def method_b(arg):
return some_data
some_data = method_b(arg)
Или я должен избегать этого?
python
coding-style
nukl
источник
источник
method_b
? (@inspector: Строго говоря, вам это нужно, но это очень полезно, когда вы начинаете заниматься функциональным программированием, в частности замыканиями).Ответы:
Это то, что ты искал? Это называется закрытием .
источник
do_it()
, что, по-видимому, будет немного сложнее, чем то, что может быть обработано некоторой арифметикой в одномreturn
выражении.Делая это, вы на самом деле не получаете много, на самом деле это замедляется
method_a
, потому что он будет определять и перекомпилировать другую функцию при каждом вызове. Учитывая , что, вероятно , было бы лучше просто префикс имени функции с подчеркиванием , чтобы указать , что это частный метод - то есть_method_b
.Я полагаю, вы можете захотеть сделать это, если определение вложенной функции по разным причинам менялось каждый раз, но это может указывать на недостаток в вашем дизайне. Тем не менее, есть это веская причина , чтобы сделать это , чтобы позволить наследованным использовать аргументы , которые были переданы на внешнюю функцию , но явно не перекладываются на них, что иногда происходит при написании функции декораторы, например. Это то, что показано в принятом ответе, хотя декоратор не определяется и не используется.
Обновить:
Вот доказательство того, что их вложение происходит медленнее (с использованием Python 3.6.1), хотя, по общему признанию, в этом тривиальном случае не так много:
Примечание. Я добавил несколько
self
аргументов к вашим образцам функций, чтобы сделать их более похожими на реальные методы (хотяmethod_b2
технически это не методTest
класса). Кроме того, вложенная функция фактически вызывается в этой версии, в отличие от вашей.источник
method_b = self._method_b
и затем вызвать,method_b
чтобы избежать повторного поиска атрибутов. (Бывает, что в последнее время я много чего делал. :)Функция внутри функции обычно используется для замыканий .
(Существует много споров о том, что именно делает закрытие закрытием .)
Вот пример использования встроенного
sum()
. Он определяетstart
один раз и использует его с тех пор:В использовании:
Встроенное закрытие Python
functools.partial
это пример закрытия.Из документов Python это примерно эквивалентно:
(Благодарю @ user225312 ниже за ответ. Мне легче найти этот пример, и, надеюсь, поможет ответить на комментарий @ mango.)
источник
Как правило, нет, не определяйте функции внутри функций.
Если у вас нет действительно веской причины. Что вы не делаете.
Почему нет?
lambda
вместо этого использовать выражение .Что является действительно хорошей причиной для определения функций внутри функций?
Когда то, что вы действительно хотите, это закрытие дингданга .
источник
На самом деле нормально объявить одну функцию внутри другой. Это особенно полезно при создании декораторов.
Однако, как правило, если функция сложная (более 10 строк), лучше объявить ее на уровне модуля.
источник
Я нашел этот вопрос, потому что хотел задать вопрос, почему это влияет на производительность, если кто-то использует вложенные функции. Я выполнил тесты для следующих функций, используя Python 3.2.5 на ноутбуке Windows с процессором Intel i5-2530M Quad Core 2,5 ГГц
Я измерял следующие 20 раз, также для square1, square2 и square5:
и получил следующие результаты
square0
не имеет вложенных функций,square1
имеет одну вложенную функцию,square2
имеет две вложенные функции иsquare5
имеет пять вложенных функций. Вложенные функции только объявлены, но не вызваны.Таким образом, если вы определили 5 вложенных функций в функции, которую вы не вызываете, тогда время выполнения функции будет вдвое больше функции без вложенной функции. Я думаю, следует соблюдать осторожность при использовании вложенных функций.
Файл Python для всего теста, который генерирует этот вывод, можно найти в ideone .
источник
Это просто принцип работы API-интерфейсов.
Используя python, рекомендуется избегать использования API в космическом пространстве (модуле или классе), функция является хорошим местом инкапсуляции.
Это может быть хорошей идеей. когда вы обеспечите
Несмотря на то, что злоупотребление этой техникой может вызвать проблемы и подразумевает недостаток дизайна.
Просто из моего опыта, Может быть, неправильно понял ваш вопрос.
источник
Таким образом, в конце концов, это в основном вопрос о том, насколько умна реализация Python или нет, особенно в случае, когда внутренняя функция не является замыканием, а просто функцией, необходимой только для помощника.
В чистом понятном дизайне, имеющем функции только там, где они необходимы и не раскрыты где-либо еще, хороший дизайн, независимо от того, встроены они в модуль, в класс как метод или внутри другой функции или метода. Когда все сделано хорошо, они действительно улучшают ясность кода.
И когда внутренняя функция является замыканием, это также может немного помочь с ясностью, даже если эта функция не возвращается из содержащей функции для использования в другом месте.
Поэтому я бы сказал, что в общем случае используйте их, но помните о возможном падении производительности, когда вы действительно обеспокоены производительностью, и удаляйте их только в том случае, если вы выполняете фактическое профилирование, которое показывает, что их лучше удалить.
Не делайте преждевременной оптимизации, просто используя «внутренние функции BAD» во всем написанном вами коде Python. Пожалуйста.
источник
Это нормально, но если вам не нужно использовать замыкание или возвращать функцию, которую я, вероятно, поместил бы на уровне модуля. Я представляю, что во втором примере кода вы имеете в виду:
в противном случае some_data будет функцией.
Наличие этого на уровне модуля позволит другим функциям использовать method_b (), и если вы используете что-то вроде Sphinx (и autodoc) для документации, это также позволит вам документировать method_b.
Вы также можете рассмотреть возможность размещения функциональности в двух методах в классе, если вы делаете что-то, что может быть представлено объектом. Это также содержит логику, если это все, что вы ищете.
источник
Сделать что-то вроде:
если бы вы запустили,
some_function()
он запустился быsome_other_function()
и вернул 42.РЕДАКТИРОВАТЬ: Я первоначально заявил, что вы не должны определять функцию внутри другого, но было отмечено, что это иногда целесообразно делать.
источник
Вы можете использовать его, чтобы избежать определения глобальных переменных. Это дает вам альтернативу для других конструкций. 3 дизайна, представляющих решение проблемы.
А) Использование функций без глобалов
Б) Использование функций с глобальными
C) Использование функций внутри другой функции
Решение C) позволяет использовать переменные в области действия внешней функции без необходимости объявлять их во внутренней функции. Может быть полезно в некоторых ситуациях.
источник
Функция В функции Python
источник