Python map zip lambda et filter

Tags:: python :: code :: développement

Python est un langage fort de principes de développement permettant la réduction conséquente de volume de code. Dans l'univers de capacités de langage, il existe des petites astuces qui deviennent véritablement des outils de développement pour permettre au développeur de ganger en efficacité. Le revers de la médaille étant de connaître assez bien Python pour avoir le reflexe qui permettra ce genre de manipulation. Parlons donc d'un ensemble de possibilités de Python qui va vous ouvrir les portes du code "court". Je parle des fonction zip, map, filter associés au fonctions lambda.

Partons d'un code python simple. Ce genre de code que vous tapez quand vous venez d'un autre langage. Ce code est évidamment juste et fonctionne. Je n'ai rien à redire à part que Python va vous permettre de le rendre plus court tout en restant optimal.



def isIPLocal(ip):
    #coupe l'ip en jeu de 4 sequences
    ip =ip.split('.')

    if ip[0]=="192" and ip[1]=="168":
        return True

    if ip[0]=="10":
        return True

    if ip[0]=="172":
        if int(ip[1]) < 32 and int(ip[1])>15:
            return True

    return False
 

Bon, reprenons rapidement le fonctionnement de cette fonction. Si l'adresse ip commence par 192.168 alors on a une ip locale, on retourne donc True. Si elle commence par "10", idem, on retourne vrai... et enfin, 3 ième cas, l'ip comence par 172 et son deuxième élément se trouve entre 16 et 31, on retourne vraie... Pour les autres cas, on retourne False.

Le code est bon, il marche. Mais voilà, Python permet de faire un peu plus court.

Tout d'abord, nous testons des chaines de caractères... non pas que ça me dérange, mais passer par des entiers va permettre d'être un peu plus efficace, et en plus, pour le cas 3, cela évitera un double "int". Mais voilà, on ne va certainemetn pas boucler sur nos élément d'ip... on va utiliser la fonction "map" qui prend en premier argument une fonction, et en second élément une liste.


...
ip = map(int, ip.split('.'))
...
 

Cela va faire une chose simple comme tout: appliquer à chaque élément retourné par "split" la fonction "int(...)", donc ip est mainentant une liste d'entier. Voyons le code:



def isIPLocal(ip):
    #coupe l'ip en jeu de 4 sequences
    ip = map(int, ip.split('.'))

    if ip[0]==192 and ip[1]==168:
        return True

    if ip[0]==10:
        return True

    if ip[0]==172:
        if ip[1] < 32 and ip[1]>15:
            return True

    return False
 

Bien, une petite réduction de code supplémentaire: inutile de faire un "and" sur le 3ième cas, on peut utiliser xrange() pour vérifier si la valeur est dans ce rang. C'est pas plus efficace mais plus lisible:



def isIPLocal(ip):
    #coupe l'ip en jeu de 4 sequences
    ip = map(int, ip.split('.'))

    if ip[0]==192 and ip[1]==168:
        return True

    if ip[0]==10:
        return True

    if ip[0]==172 and ip[1] in xrange(16,32):
        return True

    return False
 

Voilà nous avons un code plus sympa. Passons à la suite.

Maintenant, on va tester notre fonction, mais en utilisant un lot d'ip:



ips = ["192.168.0.2","88.23.45.155","10.0.0.1","172.32.10.10","1.2.3.4"]

for ip in ips:
    print ip, isIPLocal(ip)

 

Oui ça marche... mais je veux avoir la liste des ip locales, avec l'ip contenu dans la liste...:



ips = ["192.168.0.2","88.23.45.155","10.0.0.1","172.32.10.10","1.2.3.4"]

localip = []
for ip in ips:
    if isIPLocal(ip):
        localip.append(ip)

 

Voilà le cas exact et très intéressant en Python. Il est en fait inutile de faire une boucle, "filter" permet de travailler plus simplement:



ips = ["192.168.0.2","88.23.45.155","10.0.0.1","172.32.10.10","1.2.3.4"]
localip = filter(isIPLocal, ips)

 

Et voilà, une seule ligne qui remplace la boucle. "localip" est bien une liste d'adresse locales. Alors vous allez me dire "ok, mais pour avoir l'inverse? je dois refaire une fonction, ou encore pire, virer les doublons en mergant les tableaux de..." et ho... stop !

Non, on va utiliser une fonction lambda. Un fonction lambda est une fonction en une ligne, compilée directement dans le code, un peu comme une fonction inline en C. L'intérêt est qu'elle n'entre pas dans le dictionnaire de fonctions de votre code, elle ne va servir qu'au moment où on en a besoin, puis disparaitre. C'est bel et bien le principe de la fonction jetable.

Donc, clairement, pour avoir les fonctions d'adresses publiques, il faut simplement inverser isIPLocal.



ips = ["192.168.0.2","88.23.45.155","10.0.0.1","172.32.10.10","1.2.3.4"]
localip = filter(isIPLocal, ips)
privateip = filter(lambda x: not isIPLocal(x), ips)
 

Comprennez bien, 'lambda x:" signifie que "x" est l'argument de la fonction lambda. Arpès le ":" apparait la valeur de retour, sans mot clef "return"

Ici, j'inverse avec "not" le retour de la fonction isIPLocal. De ce fait, "privateip" contient que des adresses publiques.

L'intérêt ici, c'est que nous n'aurions pas put utiliser la génération de liste python avec un "[x for x in ... ]" car un test est nécessaire. Tout du moins, cela simplifie le travail.

Vous l'aurez compris, map, filter, lambda sont très intéressants. Voyons enfin "zip" qui va encore agrémenter votre développement d'un niveau.

"zip" permet de prendre deux tableaux (liste) et d'en faire une liste de tuple dont les éléments sont mappés dans l'ordre. Exemple:



 >>> a= ["foo","bar","baz"]
 >>> b = ["100","200","300"]
 >>> zip (a, b)
 [('foo', '100'), ('bar', '200'), ('baz', '300')]

 

Cela va permettre de faire des manipulations très très intéressante en conjonction avec map, filter, et des lambda.

Prenons un exemple que j'ai eut à traiter. Deux tableaux de valeurs entières dont je devais récupérer les valeurs maximales en comparaison entre chaque index. Plus clairement:


val1 = [12,45,22,15,78,41,10,2]
val2 = [8 ,22,15,75,32, 5,48,9]
 

Il me faut donc avoir la liste de valeurs telle avec max(val1[x], val2[x])... Donc on pourrait imaginer que je bouclerai sur les tableaux et que je testerai chaque valeur... mais non !


val1 = [12,45,22,15,78,41,10,2]
val2 = [8 ,22,15,75,32, 5,48,9]

res = map(lambda x: max(x[0],x[1]), zip(val1, val2))

 

C'est tout !, res vaut bien "[12, 45, 22, 75, 78, 41, 48, 9]".

Oui, on aurait put faire:


res = [max (x,y) for x,y in zip(val1, val2)]
 

En fait, la méthode "map + lambda" est juste un peu plus claire (malgré tout) et surtout plus efficace. Pour faire simple, "map" permet de ne pas trop se casser la tête sur des cas complexe... comme par exemple mapper des fonction stoquée dans un tableau à appliquer à des valeurs...


fun = [int, float, int, float]
vals = [1,2,3,4]
map(lambda x: x[0](x[1]), zip(fun, vals))
#retourne [1, 2.0, 3, 4.0]
 

Ou encore, pour charger des modules en liste:


mods = ['re','sys','os']

#mapping de fonctions
map(__import__, mods)

#plus joli que:
for m in mods: __import__(m)
 

Voilà, à vous de voir maintenant l'intérêt de ce genre de manipulation. Je vous montrerai ensuite un petit code en python qui sera en plus sujet à un défi: un code decryptage simple à casser. L'idée principale du code est de crypter des données, mais vous remarquerez l'utilisation à foison de map, de lambda, de filters...

Voilà, bon code à vous.

Utilisez le code barre pour ouvrir le ticket dans votre mobile:
This ticket on you mobile

Pas de commentaire pour le moment

Ajouter un commentaire
Veuillez répondre à la question suivante : Indiquez en chiffre ce que vaut deux et deux

Trackbacks

Pour ajouter un trackback (retrolien) sur ce ticket, utilisez cette adresse: http://www.metal3d.org/index.php/trackback/default/tb?id=blog%2F282

Tags

Blog Copix Communication PC Config Fedora Vidéo Humour Autre Web Materiel Informatique PHP Développement Mootools HTML Linux WEB IE CSS Vista Microsoft Sympa XHTML Quizz Widget Klik CWE Voeux Bonne année Musique CCRMA Son Audio MAO Reconnaissance vocale Windows Mac Compiz MacOS Mysql Sun Base de données BD Screenlets Screenlet RPM compiz Ubuntu Live FireFox Derambarsh Facebook media informations Sécurité javascript SSH Commande Marketing concours ipod wii QT Trooltech Nokia Libre Logiciels GPL Attali Gnome Dock Compiler Bench undelete reiserfs recovery recover Thread Serveur Optimisation Server Apache Album RSS Flash Air XML Firefox Blender Opensource Orange Internet LiveBox Animaux Droits Logiciels Libres Google Loi RBS netcat Bash Téléphone Spam 3D NIDIA Standards Widgets Merise UML Streaming Developpement Perl MySQL Firewall Parfeu Bayes Novell Réseau Python LVS Salon FTP Dedibox Chrome Administration IRC Gentoo troll video Nouveauté Finance Etudiant spéctacle OpenOffice Javascript Java Info Eclpise ATI design mootools KDE Bureau Design GNU C Pages Jaunes Fun Bijoux Art mail Admin vmware fedora linux VirtualBox VMWare Qemu KVM vim Grep Fglrx Webkit GTK google web JQuery Coup de gueule coup de gueule Lois SVG Raycaster Canvas Hadopi Desktop Jeux Les Sims développement astuces Screen firefox Mobile Safaru Wine bash commande astuce Wave ooc C++ C# Netbook Hercules Bureautique Twitter Safari W3C chrome kazehakaze midori navigateur gecko webkit Links Liens Pyhon Nouvelles Metal Perso Conférence JDLL PCC Roadsend OOC News Acteur Cinéma Chanteur Seven windows orthographe pcc php jdll Slide Application mysql Html twitter python screen curses SVN Android Gphone iPhone OpenGL MindMap Projet Javascrtip Ajax Guitare Tab Tablature JSON firebug Chromium Iphone Titanium music sound android ogg ogv streaming Arkyne svn subversion gnome VLC Tv encoder ffmpeg Cryptage apple microsoft HTML5 Max Apple code youtube quvi git uzbl webgl chromium

  Catalogue professionnel de musique libre


  • twitter entries...
follow me on Twitter

Valid XHTML 1.0 Strict

tumblr visitor