Maison  >  Article  >  développement back-end  >  [python] Un premier aperçu de la « programmation fonctionnelle »

[python] Un premier aperçu de la « programmation fonctionnelle »

高洛峰
高洛峰original
2017-02-16 11:09:491299parcourir

Programmation fonctionnelle

Le semestre dernier, j'ai suivi un cours intitulé « Intelligence artificielle ». Le professeur nous a forcé à apprendre un langage appelé prologue, c'était vraiment inconfortable. La façon de penser était complètement différente de ce qui se passait. nous avons appris avant. Ma vie était différente. J'ai longtemps pensé à écrire la Tour de Hanoï. Finalement, j'ai trouvé un morceau de code sur Internet et je l'ai modifié (de peur d'être découvert par le professeur pour l'avoir plagié). avant de l'écrire. J'ai posté un paragraphe pour avoir une idée :

hanoi(N) :- dohanoi(N, 'a', 'b', 'c').
dohanoi(0, _ , _ , _ )    :- !.
dohanoi(N, A, B, C)    :-
  N1 is N-1,
  dohanoi(N1, A, C, B),
  writeln([move, N, A-->C]), 
  dohanoi(N1, B, A, C).

Je l'avais presque compris à l'époque, mais la raison principale était qu'il y avait trop peu d'informations et que le débogage était hors de propos. question. Chaque fois que je rencontrais un bug, je prenais du retard. Même maintenant, je me sens un peu étourdi. Cependant, on dit que prolog pourrait rivaliser avec Lisp à l'époque, et je me suis récemment un peu intéressé à Lisp. Après avoir terminé ces choses, je rendrai hommage à ce type de langage fonctionnel.

Qu'est-ce que la programmation fonctionnelle ? Liao Da a écrit ici :

La programmation fonctionnelle est un paradigme de programmation avec un haut degré d'abstraction. Les fonctions écrites dans des langages de programmation purement fonctionnels n'ont donc aucune variable pour aucune fonction. l'entrée est déterminée, la sortie est déterminée. Nous appelons cette fonction pure sans effets secondaires. Dans les langages de programmation qui permettent l'utilisation de variables, puisque le statut de la variable à l'intérieur de la fonction est incertain, la même entrée peut donner lieu à des sorties différentes. Par conséquent, ce type de fonction a des effets secondaires.

Peut-être que vous ne le comprenez toujours pas après l'avoir lu. Ne vous inquiétez pas, lisons d'abord ces sections.

Fonctions d'ordre supérieur

En mathématiques et en informatique, une fonction d'ordre supérieur est une fonction qui satisfait à au moins une des conditions suivantes :

  • Accepte une ou plusieurs fonctions A prend en entrée

  • et génère une fonction

C'est-à-dire passer la fonction elle-même en paramètre, ou renvoyer une fonction.

Par exemple, vous pouvez attribuer une fonction à une variable comme une affectation normale :

>>> min(1, 2)
1
>>> f = min
>>> f(1, 2)
1
>>> f
<built-in function min>
>>> min
<built-in function min>

Vous pouvez également attribuer une valeur à une fonction (suite du code) :

>>> min = 10
>>> min(1, 2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'int' object is not callable
>>> f(1, 2)
1
>>> min = f
>>> min(1, 2)
1

Très bien Passer des paramètres, par exemple, une fonction qui calcule la somme de tous les nombres :

>>> def add(a, b):
...     return a+b
...

>>> def mysum(f, *l):
...     a = 0
...     for i in l:
...             a = f(a, i)
...     return a
...
>>> mysum(add, 1, 2, 3)
6
>>> mysum(add, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
55

Bien sûr, remplacer ce f par une multiplication revient à calculer le produit de tous les nombres.

Jetons un coup d'œil à certaines des fonctions d'ordre supérieur intégrées à Python, qui sont souvent utilisées.

map/reduce

Je me souviens avoir vaguement entendu ce mot lorsque j'ai suivi un cours de cloud computing le semestre dernier, mais le cours était très ennuyeux, donc je ne l'ai pas beaucoup écouté, semble-t-il. trouver ça étrange quand je le vois ici Trop pareil ? ?

Mais il n’y a pas grand chose à dire. Parlons brièvement du rôle de chaque fonction.

Pour la carte, sa formule de calcul peut être vue comme ceci :

map(f, [x1, x2, ..., xn]) = [f(x1), f(x2), ..., f(xn)]

Pour réduire, sa formule de calcul peut être vue comme ceci :

reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4)

Liao Dana dit très clairement.

filter

filter est similaire à la fonction map, acceptant une fonction et itérable, et renvoyant une liste, mais sa fonction est de déterminer s'il faut conserver la valeur en fonction du fait que la fonction renvoie une valeur est vrai. Par exemple :

def is_odd(n):
    return n % 2 == 1

list(filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15]))
# 结果: [1, 5, 9, 15]

trié

La fonction triée est également une fonction d'ordre supérieur. Passer la fonction à la clé de paramètre peut traiter la séquence à trier via la fonction clé, puis. triez-le, mais cela ne changera pas la valeur de la séquence, par exemple :

>>> sorted([36, 5, -12, 9, -21], key=abs)
[5, 9, -12, -21, 36]

Décorateur (décorateur)

Je ne parlerai pas de fonctions anonymes, je prendrai un. regardez-les de plus près lorsque je les utiliserai plus tard. Je me souviens avoir déjà regardé le décorateur de Flask, je l'étudiais depuis longtemps, je vais donc le revoir cette fois.

Décorateur simple

Le premier est un décorateur simple qui imprime le journal avant chaque appel de fonction :

import logging

def log(func):
    def wrapper(*args, **kw):
        logging.warn("%s is running" % func.__name__)
        func(*args, **kw)
    return wrapper

C'est un décorateur extrêmement simple, comment l'utiliser ? La première utilisation que j'ai vue était d'ajouter @ avant la fonction à décorer, mais en fait c'est un sucre syntaxique de Python. L'utilisation la plus originale est plus compréhensible. Définissez d'abord une fonction f :

def f():
    print("in function f")

f = log(f)
<.>Après cette définition, nous appelons la fonction f :

>>> f()
WARNING:root:f is running
in function f
Le résultat de l'utilisation de @log est le même. En fait, le symbole @ sert de sucre syntaxique pour le décorateur et a la même fonction que. l'instruction d'affectation précédente. , rendant le code plus concis et clair, évitant une autre opération d'affectation, comme la suivante :

@log
def f():
    print("in function f")
Décorateur avec paramètres

Parfois, nous devons également transmettre des paramètres à le décorateur Pour saisir des paramètres, tels que l'état, le niveau et d'autres informations, il vous suffit d'« envelopper » une couche de fonctions en dehors de la fonction wrapper, comme indiqué ci-dessous :

import logging

def log(level):
    def decorator(func):
        def wrapper(*args, **kw):
            logging.warn("%s is running at level %d" % (func.__name__, level))
            return func(*args, **kw)
        return wrapper
    return decorator

@log(2)
def f():
    print("in function f")
    
>>> f()
WARNING:root:f is running at level 2
in function f
Pour une compréhension plus approfondie

Afin de mieux comprendre Decorator, nous pouvons imprimer l'attribut name de la fonction f :

#对于不加装饰器的 f,其 name 不变
>>> def f():
...     print("in function f")
...
>>> f.__name__
'f'

#对于添加装饰器的函数,其 name 改变了
>>> @log
... def f():
...     print("in function f")
...
>>> f.__name__
'wrapper'
En contactant la première déclaration d'affectation du décorateur, nous pouvons à peu près comprendre ce qui s'est passé :

fait valoir le point f to log (La valeur de retour de f) est la fonction wrapper. Chaque fois que la fonction d'origine f est exécutée, la fonction wrapper sera appelée. Dans notre exemple, le journal est imprimé en premier, puis la fonction d'origine f est exécutée. f = log(f)

Cependant, il y a un problème avec cela. Cela entraîne le remplacement des méta-informations de la fonction d'origine f, et de nombreuses informations sur f disparaissent. C'est difficile à accepter, mais heureusement nous l'avons. module functools. Modifier La fonction est :

import functools
import logging

def log(func):
    functools.wraps(func)
    def wrapper(*args, **kw):
        logging.warn("%s is running" % func.__name__)
        func(*args, **kw)
    return wrapper

>>> @log
... def f():
...     print("in function f")
...
>>> f.__name__
'f'
De plus, vous pouvez ajouter plusieurs décorateurs à la même fonction :

@a
@b
@c
def f ():


# 等价于

f = a(b(c(f)))
Résumé

Je ne suis pas très familier avec la programmation fonctionnelle. Comprenez, voici juste une brève compréhension de son concept, il est généralement nettement plus utile d'utiliser la programmation impérative. Il existe cependant des langages purement fonctionnels, comme Haskell ou Lisp, et leur apprentissage ouvrira une nouvelle façon de penser.

Pour plus d'articles [python] liés à la "Programmation fonctionnelle", veuillez faire attention au site Web PHP chinois !

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn