Prosty przykład. Dwie metody, jedna wywoływana z drugiej:
def method_a(arg):
some_data = method_b(arg)
def method_b(arg):
return some_data
W Pythonie możemy zadeklarować def
wewnątrz innego def
. Więc jeśli method_b
jest to wymagane i wywoływane tylko z method_a
, czy powinienem zadeklarować w method_b
środku method_a
? lubię to :
def method_a(arg):
def method_b(arg):
return some_data
some_data = method_b(arg)
Czy powinienem tego unikać?
python
coding-style
nukl
źródło
źródło
method_b
? (@inspector: Ściśle rzecz biorąc, musisz to robić, ale jest to niezwykle przydatne, gdy zaczynasz zajmować się programowaniem funkcjonalnym, w szczególności zamknięciami).Odpowiedzi:
Czy tego szukałeś? Nazywa się to zamknięciem .
źródło
do_it()
prawdopodobnie byłoby nieco bardziej skomplikowane niż to, co można obsłużyć za pomocą jakiejś arytmetyki w pojedynczejreturn
instrukcji.Tak naprawdę niewiele zyskujesz, robiąc to, w rzeczywistości spowalnia to
method_a
, ponieważ definiuje i rekompiluje inną funkcję za każdym razem, gdy jest wywoływana. Biorąc to pod uwagę, prawdopodobnie lepiej byłoby po prostu poprzedzić nazwę funkcji podkreśleniem, aby wskazać, że jest to metoda prywatna - tj_method_b
.Przypuszczam, że może chcesz to zrobić, jeśli definicja funkcji zagnieżdżonej za zmieniać za każdym razem z jakiegoś powodu, ale może wskazywać na błąd w projekcie. Powiedział, że jest ważny powód, aby to zrobić, aby umożliwić funkcja zagnieżdżona używać argumentów, które zostały przekazane do funkcji zewnętrznej, ale nie wprost na nich przerzucone, który czasami pojawia się podczas pisania dekoratorów funkcyjnych, na przykład. To właśnie jest pokazane w zaakceptowanej odpowiedzi, mimo że dekorator nie jest definiowany ani używany.
Aktualizacja:
Oto dowód na to, że zagnieżdżanie ich jest wolniejsze (przy użyciu Pythona 3.6.1), chociaż w tym trywialnym przypadku nie za dużo:
Uwaga Dodałem kilka
self
argumentów do twoich przykładowych funkcji, aby uczynić je bardziej podobnymi do prawdziwych metod (chociażmethod_b2
nadal nie jest technicznie metodąTest
klasy). Również funkcja zagnieżdżona jest faktycznie wywoływana w tej wersji, w przeciwieństwie do twojej.źródło
method_b = self._method_b
A następnie wywołując,method_b
aby uniknąć powtarzających się wyszukiwań atrybutów. (Zdarza się, że ostatnio robię DUŻO czasu. :)Funkcja wewnątrz funkcji jest powszechnie używana do domknięć .
(Istnieje wiele sporów co do tego, co dokładnie sprawia , że zamknięcie jest zamknięciem ).
Oto przykład użycia wbudowanego
sum()
. Definiujestart
raz i używa go odtąd:W użyciu:
Wbudowane zamknięcie w języku Python
functools.partial
jest przykładem zamknięcia.Z dokumentacji Pythona jest to mniej więcej odpowiednik:
(Uznanie dla @ user225312 poniżej za odpowiedź. Uważam, że ten przykład jest łatwiejszy do zrozumienia i mam nadzieję, że pomogę odpowiedzieć na komentarz @ mango.)
źródło
Generalnie nie, nie definiuj funkcji wewnątrz funkcji.
Chyba że masz naprawdę dobry powód. Czego nie robisz.
Dlaczego nie?
lambda
zamiast tego użyć wyrażenia .Jaki jest naprawdę dobry powód, aby definiować funkcje wewnątrz funkcji?
Kiedy to, czego naprawdę chcesz, to zamknięcie dingdang .
źródło
Właściwie dobrze jest zadeklarować jedną funkcję wewnątrz innej. Jest to szczególnie przydatne przy tworzeniu dekoratorów.
Jednak z reguły, jeśli funkcja jest złożona (więcej niż 10 linii), lepszym pomysłem może być zadeklarowanie jej na poziomie modułu.
źródło
Znalazłem to pytanie, ponieważ chciałem zadać pytanie, dlaczego użycie funkcji zagnieżdżonych ma wpływ na wydajność. Przeprowadziłem testy następujących funkcji przy użyciu Pythona 3.2.5 na notebooku z systemem Windows z czterordzeniowym procesorem Intel i5-2530M 2,5 GHz
Zmierzyłem następujące 20 razy, również dla kwadratu1, kwadratu2 i kwadratu5:
i otrzymałem następujące wyniki
square0
nie ma funkcji zagnieżdżonej,square1
ma jedną funkcję zagnieżdżoną,square2
ma dwie funkcje zagnieżdżone isquare5
ma pięć funkcji zagnieżdżonych. Zagnieżdżone funkcje są tylko deklarowane, ale nie są wywoływane.Więc jeśli zdefiniowałeś 5 zagnieżdżonych funkcji w funkcji, której nie wywołujesz, to czas wykonania funkcji jest dwukrotnie dłuższy niż funkcji bez funkcji zagnieżdżonej. Myślę, że należy zachować ostrożność podczas korzystania z funkcji zagnieżdżonych.
Plik Pythona dla całego testu, który generuje te dane wyjściowe, można znaleźć pod adresem ideone .
źródło
To tylko zasada dotycząca interfejsów API ekspozycji.
Używając Pythona, dobrym pomysłem jest unikanie ekspozycji API w przestrzeni kosmicznej (moduł lub klasa), funkcja jest dobrym miejscem do hermetyzacji.
To mógłby być dobry pomysł. kiedy zapewniasz
Mimo to, nadużywanie tej techniki może powodować problemy i sugeruje wadę projektową.
Tylko z mojego doświadczenia, może źle zrozumiałem twoje pytanie.
źródło
W końcu jest to w dużej mierze pytanie o to, jak inteligentna jest implementacja Pythona, szczególnie w przypadku, gdy funkcja wewnętrzna nie jest zamknięciem, ale po prostu potrzebnym pomocnikiem w funkcji.
W czystym, zrozumiałym projekcie, w którym funkcje są tylko tam, gdzie są potrzebne i nie są ujawniane gdzie indziej, jest dobrym projektem, niezależnie od tego, czy są one osadzone w module, klasie jako metodzie, czy w innej funkcji lub metodzie. Dobrze wykonane naprawdę poprawiają przejrzystość kodu.
A kiedy funkcja wewnętrzna jest zamknięciem, które również może pomóc w przejrzystości, nawet jeśli ta funkcja nie jest zwracana z funkcji zawierającej do użycia w innym miejscu.
Powiedziałbym więc, że generalnie używaj ich, ale pamiętaj o możliwym spadku wydajności, gdy faktycznie martwisz się o wydajność, i usuwaj je tylko wtedy, gdy wykonasz faktyczne profilowanie, które pokazuje, że najlepiej je usunąć.
Nie wykonuj przedwczesnej optymalizacji, używając po prostu „ZŁE funkcje wewnętrzne” w całym kodzie Pythona, który piszesz. Proszę.
źródło
Robienie tego w ten sposób jest całkowicie w porządku, ale chyba że musisz użyć zamknięcia lub zwrócić funkcji, prawdopodobnie umieściłbym to na poziomie modułu. Wyobrażam sobie, że w drugim przykładzie kodu masz na myśli:
w przeciwnym razie some_data będzie funkcją.
Posiadanie go na poziomie modułu pozwoli innym funkcjom używać method_b (), a jeśli używasz czegoś takiego jak Sphinx (i autodoc) do dokumentacji, pozwoli ci to również udokumentować method_b.
Możesz również rozważyć umieszczenie funkcji w dwóch metodach w klasie, jeśli robisz coś, co może być reprezentowane przez obiekt. Zawiera również logikę, jeśli to wszystko, czego szukasz.
źródło
Zrób coś takiego:
jeśli miałbyś uruchomić,
some_function()
to uruchomi sięsome_other_function()
i zwróci 42.EDYCJA: Początkowo stwierdziłem, że nie powinno się definiować funkcji wewnątrz innej, ale wskazano, że czasami jest to praktyczne.
źródło
Możesz go użyć, aby uniknąć definiowania zmiennych globalnych. Daje to alternatywę dla innych projektów. 3 projekty przedstawiające rozwiązanie problemu.
A) Używanie funkcji bez globali
B) Używanie funkcji z globalnymi
C) Używanie funkcji wewnątrz innej funkcji
Rozwiązanie C) pozwala na użycie zmiennych w zakresie funkcji zewnętrznej bez konieczności deklarowania ich w funkcji wewnętrznej. Może się przydać w niektórych sytuacjach.
źródło
Funkcja W funkcji python
źródło