J'ai demandé auparavant comment le fonctions imbriquées travail, mais malheureusement, je ne suis toujours pas tout à fait tu piges. Pour mieux comprendre, quelqu'un peut-il faire preuve de quelques exemples de fonctionnalités imbriquées de fonctions imbriquées? P>
Merci beaucoup P>
8 Réponses :
Les décorateurs sont une utilisation très populaire pour les fonctions imbriquées. Voici un exemple de décorateur qui imprime une déclaration avant et après tout appel à la fonction décorée.
def entry_exit(f): def new_f(*args, **kwargs): print "Entering", f.__name__ f(*args, **kwargs) print "Exited", f.__name__ return new_f @entry_exit def func1(): print "inside func1()" @entry_exit def func2(): print "inside func2()" func1() func2() print func1.__name__
C'est en fait un autre sujet à apprendre, mais si vous regardez les trucs sur «Utilisation de fonctions comme décorateurs», vous verrez quelques exemples de fonctions imbriquées. P>
Fonctions imbriquées Évitez d'encombrer d'autres parties du programme avec d'autres fonctions et variables qui ne donnent aucun sens localement.
Une fonction de retour de Fibonacci pourrait être définie comme suit: P>
>>> def fib(n): def rec(): return fib(n-1) + fib(n-2) if n == 0: return 0 elif n == 1: return 1 else: return rec() >>> map(fib, range(10)) [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
Il est probablement intéressant de noter que chaque fois que FIB est appelé, un nouvel objet de fonction REC est créé. Dans les cas de nettoyage de code, cela peut souvent être indésirable. Pour des choses comme des décorateurs, c'est essentiellement nécessaire.
Je n'ai eu qu'à utiliser des fonctions imbriquées lors de la création de décorateurs. Une fonction imbriquée est essentiellement une façon d'ajouter un comportement à une fonction sans savoir quelle est la fonction que vous ajoutez un comportement à. ignorer tous les Mumbo Jumbo de la fonction "PrintCall" pour En ce moment et concentrez uniquement la fonction «Sayhello» et ci-dessous. Ce que nous faisons ici, c'est que nous voulons imprimer la manière dont la fonction "Sayhello" a été appelée à chaque fois qu'elle est appelée sans savoir ni modifier la fonction "Sayhello". Nous redéfinissons donc la fonction "Sayhello" en le passant à "PrintCall", qui renvoie une nouvelle fonction qui fait la fonction "Sayhello" et imprime la manière dont la fonction "Sayhello" a été appelée. C'est le concept de décorateurs. P> Mettre "@printcall" au-dessus de la définition Sayhello accomplit la même chose: P> @printCall
def sayHello(name):
print "Hello, my name is %s" % (name)
if __name__ == "__main__":
name = "Nimbuz"
sayHello(name)
J'ai réalisé que les "getargkwargstrings" sont également une fonction imbriquée. Il est imbriqué car il n'est nécessaire que de la fonction "PrintCall" et n'a pas besoin d'être accessible autrement.
Comme M. Fooz l'a mentionné ci-dessus dans un autre exemple, la fonction «getargkwargstrings» imbriquée à l'intérieur de «PrintCall» sera définie chaque fois que la fonction «PrintCall» est appelée qui peut être souhaitée ou non souhaitable.
Votre question m'a fait curieux, alors j'ai regardé dans un code réel du monde: la bibliothèque standard Python. J'ai trouvé 67 exemples de fonctions imbriquées. Voici quelques-uns, avec des explications.
Une raison très simple d'utiliser une fonction imbriquée est simplement que la fonction que vous définissez n'a pas besoin d'être globale, car seule la fonction enfermante l'utilise. Un exemple typique de Python's Quopri.py standard Module de bibliothèque: P>
def baba(xdummy, ydummy): clearscreen() bye() ... tri.write(" Click me!", font = ("Courier", 12, "bold") ) tri.onclick(baba, 1)
Ce sont de bons exemples, mais ils pourraient tous être écrits comme des fonctions globales sans perte de fonctionnalité. Les fonctions imbriquées sont plus que du sucre syntaxique! vous devriez donner quelques exemples où ils sont nécessaires
Il convient également de noter que les fonctions imbriquées ajoutent des frais généraux. Chaque fois que la fonction extérieure est appelée, Python crée une nouvelle instance de la fonction intérieure. Dans beaucoup de cas cela n'a pas d'importance, mais parfois.
Ils sont utiles lors de l'utilisation de fonctions qui prennent d'autres fonctions comme entrée. Dites que vous êtes dans une fonction et souhaitez trier une liste d'éléments basés sur la valeur d'éléments d'une dict: vous pouvez simplement définir Un autre cas d'utilisation est des rappels. p> p>
OK, outre les décorateurs: dites que vous avez eu une application dans laquelle vous devez trier une liste de chaînes en fonction de sous-chaînes variant de temps à autre. Maintenant, les fonctions CODE> triés code> prend une clé code> = code> une fonction d'un argument: les éléments (chaînes dans ce cas) à trier. Alors, comment dire à cette fonction qui sous-tendent de trier? Une fonction de fermeture ou imbriquée est parfaite pour cela: simple eh? Vous pouvez étendre à ce sujet en encapsulant début et arrêtez-vous dans un tuple ou un objet de tranche, puis de transmettre une séquence ou irable de ceux-ci au tri_key_factory. P> P>
Un autre exemple (très simple). Une fonction qui renvoie une autre fonction. Notez comment la fonction interne (renvoyée) peut utiliser des variables de la portée de la fonction extérieure.
def create_adder(x): def _adder(y): return x + y return _adder add2 = create_adder(2) add100 = create_adder(100) >>> add2(50) 52 >>> add100(50) 150
Est-ce le fait que la fonction interne conserve les valeurs des variables dans la portée enfermante que vous n'obtenez pas?