jeudi 17 décembre 2009

Quelques caratéristiques avancées du langage Python

Le langage Python dispose de quelques fonctions ou classes avancées qui peuvent se montrer vraiment utile dans des domaines pointus et pour le développement d'applications d'envergure.
Cet article reprend également quelques fonctions relatives aux éléments itérables.



__import__
__import__ est une primitive du langage permettant de charger un module (fichier .py) à la volée.
Cette primitive est principalement utilisé dans le cadre d'activation de modules plug-ins.

compile
La fonction compile permet de compiler du code source Pyhton à la volée.
Ce code source pouvant être contenu dans une chaine de caractère.
Par la suite, ce code compilé pourra être exécuté à l'aide de la primitive exec() ou eval().
Les cas d'utilisation de compile sont rare. Cependant, cette fonctionnalité convient très bien aux logiciels évolutifs (capable de se modifier par eux-mêmes).
Note:
Lors de l'utilisation de la fonction compile, il faut indique le mode de compilation.
Pour la compilation d'une expression à évaluer; le mode 'eval' convient très bien.
Bien qu'il soit indiqué que le mode 'single' convienne pour plusieurs instructions,  je n'ai eu un résultat probant  qu'en utilisant le mode 'exec' (voir l'exemple relatif à eval).

eval
Permet d'effectuer une évaluation (ou exécution) de code Python à la volée.
La fonction eval permet également d'utiliser le contexte actuel d'exécution (les variables définie et accessible au code appelant le seront également pour le code évalué) ou de définir le contexte d'exécution.
>>> myInt = 123
>>> sToEvaluate = 'myInt * 2'
>>> eval( sToEvaluate )
246
>>> # Modify the execution context
>>> eval( sToEvaluate, {'myInt' : 12} )
24
 
>>> sToEvaluate = 'x = 3\nprint( "%s * %s = %s" % (x, myInt, x*myInt) )'
>>> # Use 'exec' compilation mode because there are several lines!
>>> _compiled = compile( sToEvaluate, '/dev/null', 'exec' )
>>> eval( _compiled, {'myInt':12} )
3 * 12 = 36

execfile
Comme son nom le suggère, execfile permet d'exécuter le code contenu dans un fichier Python.
Cette exécution peut exploiter le contexte actuel ou redéfinir un contexte.

enumerate
Itération. Permet d'associer un indice/index numérique à chaque élément du contenu itérable.
>>> myList = [ 1, 13, 22, 4, 6, 17, 88, 65 ]
>>> for index, valeur in enumerate( myList ):
 print( 'valeur à l''index %s : %s' % (index, valeur) )

 
valeur à lindex 0 : 1
valeur à lindex 1 : 13
valeur à lindex 2 : 22
valeur à lindex 3 : 4
valeur à lindex 4 : 6
valeur à lindex 5 : 17
valeur à lindex 6 : 88
valeur à lindex 7 : 65
>>> myString = 'Hello !'
>>> for index, char in enumerate( myString ):
 print ( '%s - %s ' % (index, char) )

 
0 - H 
1 - e 
2 - l 
3 - l 
4 - o 
5 -   
6 - ! 

filter
Itération. La fonction filter permet de filtrer le contenu d'un tuple, list ou chaîne de caractères à l'aide d'une fonction. Seuls les éléments retournant True à la fonction de filtrage seront conservés.
None peut également être utilisé comme fonction de filtrage.
Dans ce cas, seul les éléments évalués comme True seront conservés (autrement dit, tout élément/objet ayant une référence). C'est une méthode bien pratique pour éliminer les éléments None d'une liste.
>>> myList = [ 1, 13, 22, 4, 6, 17, 88, 65 ]
>>> def myFilter( i ):
 return i>=10

>>> myFiltered = filter( myFilter, myList )
>>> for item in myFiltered:
 print item

 
13
22
17
88
65
>>> myString = "Voici une chaine de caractère. Je veux enlever les espaces"
>>> def isNotSpace( aChar ):
 return aChar != ' '

>>> myFilteredString = filter( isNotSpace, myString )
>>> print myFilteredString
Voiciunechainedecaractère.Jeveuxenleverlesespaces

reduce
Itération. Reduce permet d'appliquer une fonction de transformation de façon continu aux éléments d'une séquence.
Les 2 premiers éléments de la séquence sont utilisé avec la fonction.
Le résultat est alors utilisé avec le 3ième élément de la séquence pour rappeler la fonction.
Le nouveau résultat obtenu est alors utilisé avec le 4ième élément de la séquence pour rappeler la fonction.
Et ainsi de suite jusqu'à la fin de la séquence.

L'exemple suivant illustre parfaitement le fonctionnement de la fonction reduce.

>>> def somme( x, y):
...     print( '%d + %d = %d' % (x,y,x+y) )
...     return x+y
... 
>>> 
>>> reduce( somme, [1,2,3,4,5] )
1 + 2 = 3
3 + 3 = 6
6 + 4 = 10
10 + 5 = 15
15

Reduce peut également prendre une valeur initiale en troisième argument.
Cela permet de reprendre/compléter une opération reduce avec des nouvelles données.
>>> # poursuivre le calcul avec le dernier résultat obtenu (15) comme
>>> # valeur initiale
>>> reduce( somme, [6,7,8,9,10], 15 )
15 + 6 = 21
21 + 7 = 28
28 + 8 = 36
36 + 9 = 45
45 + 10 = 55
55
>>> # la somme des nombres de 1 à 10 fait 55

Cas d'utilisation:
  • traitement de flux de donnée.
  • Calcul récursif sur série de donnée (ex: calcul de moyenne).
map
Itération. Permet d'appliquer une fonction de transformation à chacun des éléments d'une structure itérable.
A noter que map peut être utilisé avec plusieurs listes. Dans ce cas, les éléments seront joints (un à un) et passés en paramètres de la fonction de transformation.
La fonction de transformation peut être None, dans ce cas, les éléments sont retournés (joint) tel quel et combinés en Tuple. Si l'une des liste est plus courte le tuple contiendra None pour l'élément manquant.
>>> myList = [1, 13, 22, 4, 6, 17, 88, 65]
>>> def mapTest( item ):
 return item*2

>>> newList = map( mapTest, myList )
>>> newList
[2, 26, 44, 8, 12, 34, 176, 130]

>>> myList = [1, 13, 22, 4, 6, 17, 88, 65]
>>> myList2 = ['A', 'b', 'c', 'd']
>>> def mapTest2( item1, item2 ):
        # str the items to avoids the error:
        # TypeError: cannot concatenate 'str' and 'NoneType' objects
 return str(item1)+'-'+str(item2)
>>> newList = map( mapTest2, myList, myList2 )
>>> newList
['1-A', '13-b', '22-c', '4-d', '6-None', '17-None', '88-None', '65-None']

>>> # mapping with None as function
>>> #   In this case this create TUPLES
>>> newList = map( None, myList, myList2 )
>>> newList
[(1, 'A'), (13, 'b'), (22, 'c'), (4, 'd'), (6, None), (17, None), (88, None), (65, None)]

>>> # mapping strings with None as function
>>> str1 = 'elements'
>>> str2 = 'langage'
>>> newList = map( None, str1, str2 )
>>> newList
[('e', 'l'), ('l', 'a'), ('e', 'n'), ('m', 'g'), ('e', 'a'), ('n', 'g'), ('t', 'e'), ('s', None)]
>>> # Autre usage des tuples
>>> for item1, item2 in map( None, str1, str2 ):
 print str( item1 )
 print ' +-> '+str( item2 ) 
e
 +-> l
l
 +-> a
e
 +-> n
m
 +-> g
e
 +-> a
n
 +-> g
t
 +-> e
s
 +-> None

all
Itération. Permet de tester l'homogénéité d'une séquence.
La fonction all retourne true si tous tous les éléments d'une séquence peuvent être évalués comme vrai.
Les éléments évalués peuvent être des références d'objets (assignés=True ou None=False) ou des expressions booléennes.
>>> mySeq1 = [ 1, 2, 'a', None ]
>>> mySeq2 = [ 1, 2, 'a', 3 ]
>>> mySeq3 = [ 1, 10, 20, 60 ]

>>> # Teste si tous les éléments sont assignés
>>> all( mySeq1 )
False
>>> all( mySeq2 )
True

>>> # Test d'homogénéité
>>> all( isinstance( el, int ) for el in mySeq1 )
False
>>> all( isinstance( el, int ) for el in mySeq2 )
False
>>> all( isinstance( el, int ) for el in mySeq3 )
True

>>> # Utilisation des [ ] pour construire un élément itérable
>>> print [ isinstance( el, int ) for el in mySeq3 ]
[True, True, True, True]
>>> # Test avec la nouvelle notation
>>> print all( [ isinstance( el, int ) for el in mySeq3 ] )
True

any
Itération. Permet de tester facilement le contenu d'une séquence.
La fonction any retourne true si au moins un des éléments de la séquence séquence peut être évalué comme vrai.
Les éléments évalués peuvent être des références d'objets (assignés ou None) ou des expressions booléennes.

>>> mySeq1 = [ 1, 2, 'a', None ]
>>> mySeq2 = [ 1, 2, 'a', 3 ]
>>> mySeq3 = [ 1, 10, 20, 60 ]

>>> print any( el > 10 for el in mySeq1 )
True
>>> print any( el > 10 for el in mySeq2 )
True
>>> print any( el > 10 for el in mySeq3 )
True
>>> print any( [ el > 10 for el in mySeq1 ] )
True
>>> print any( [ el > 10 for el in mySeq2 ] )
True
>>> print any( [ el > 10 for el in mySeq3 ] )
True
>>> print any( [ isinstance( el, str ) for el in mySeq1 ] )
True
>>> print any( [ isinstance( el, str ) for el in mySeq2 ] )
True
>>> print any( [ isinstance( el, str ) for el in mySeq3 ] )
False
Petit exemple complémentaire sur le blog amix.dk

Aucun commentaire: