d'abord, rends compte que je ne peux pas vous donner une liste complète. Si vous deviez vous demander «pourquoi les tournevis sont-ils utiles?», Je parlerais des vis et des couvercles de boîtes de peinture, mais manquerais leur valeur dans l'inspection des termites. Lorsque vous demandez: «Pourquoi les fonctions imbriquées sont-elles utiles?», Je peux vous parler de la portée, des fermetures et des points d'entrée.
Premièrement, l'imbrication peut être une alternative aux classes. J'ai récemment écrit un code de rendu qui prenait un nom de fichier pour un code de balisage spécialisé et renvoyait un bitmap. Cela conduit naturellement à des fonctions nommées grab_markup_from_filename() et render_text_onto_image() et autres. L'organisation la plus propre était un point d'entrée nommé generate_png_from_markup_filename(). Le point d'entrée a fait son travail en utilisant des fonctions imbriquées pour accomplir sa tâche. Il n'y avait pas besoin d'une classe, car il n'y avait pas d'objet avec état. Mon alternative était de créer un module avec des méthodes privées cachant mes aides, mais ce serait plus désordonné.
def generate_png_from_markup_filename(filename):
def grab_markup_from_filename():
...
... # code that calls grab_markup_from_filename() to make the image
return image
Deuxièmement, j'utilise l'emboîtement pour les fermetures. L'exemple le plus courant est celui de la création de décorateurs. L'astuce est que je renvoie une référence à une fonction interne, de sorte que la fonction interne et la valeur du paramètre externe ne sont pas collectées.
def verify_admin(function_to_call):
def call_on_verify_admin(*args, **kwargs):
if is_admin(global.session.user):
return function_to_call(*args, **kwargs)
else:
throw Exception("Not Admin")
return call_on_verify_admin # the return value of verify_admin()
utiliser cette façon:
def update_price(item, price):
database.lookup(item).set_field('price', price)
update_price = verify_admin(update_price)
ou, de façon plus concise:
@verify_admin
def update_price(item, price):
database.lookup(item).set_field('price', price)
Et oui, il devrait être difficile à tracer. Rappelez-vous que "def" est juste une autre déclaration. Donc, voici deux endroits où les classes imbriquées sont utiles. Il y en a plus. C'est un outil.
En fait, la syntaxe de l'exemple C# (la syntaxe de délégué anonyme) n'est pas nouvelle à 3.5; c'était avec nous en 2.0. Si vous aviez utilisé une fonction lambda, cela aurait été la syntaxe C# 3. –
PS - J'aime votre musique. –
@Erik: Merde, je savais que je bousillerais quelque part. ;-) –