Bonjour,

Comment utiliser map(f,...) lorsqu'un des arguments de f() est constant (i.e ne dépend pas de l'itérable) ?

Pour l'instant je multiplie une liste avec l'argument constant. A priori peu efficace (un appel à len() et la multiplication de la liste).

Voici un exemple (voir fonction f5() ), ou j'essaye d'optimiser le problème suivant: créer la liste l_x des o.x depuis une liste l d'objets o ayant un champ x.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
 
def get_x(r):
    return r.x
import random    
class obj:
    def __init__(self): self.x= random.random()
    def f(self): return self.x
 
o= obj()
l= [o]*1000
 
def f1():
    l_x=[]
    for k in l: l_x.append(k.x)
def f2():
    l_x=[k.x for k in l]
def f3():        
    l_x= map(get_x,l)
def f4():        
    l_x= map(obj.f,l)
"Exemple de map avec argument constant"
def f5():
    l_constantArg= ["x"]*len(l)
    l_x= map(getattr,l,l_constantArg)
 
def run(fun,repet,name,*args,**kargs):
    """ appel fun(*args,**kwargs) repet. fois. Mesure et affiche le temps """
    R= xrange(repet)
    t= time.clock()
    for m in R:
        res= fun(*args,**kargs)
    dt= time.clock() - t
    print "fun %s has run.%s in %s " %(name,repet,dt)
 
run(f1,100,'for k in :',l)
run(f2,100,'[list_comp]',l)   
run(f3,100,'map global get_x()',l)
run(f4,100,'map class.get()',l)
run(f5,100,'map getattr',l)

Resultats (debug mode san psyko):
fun for k in : has run.100 in 0.0350195346057
fun [list_comp] has run.100 in 0.0227143393923
fun map global get_x() has run.100 in 0.798853485569
fun map class.get() has run.100 in 0.848990583999
fun map getattr has run.100 in 0.0160827702962

NB: Le gain dépend fortement de la longueur de la liste l. Il n'a pas l'air monotone.

Resultats (avec psyko):
fun for k in : has run.100 in 0.019553602483
fun [list_comp] has run.100 in 0.00934755674255
fun map global get_x() has run.100 in 0.0231512664319
fun map class.get() has run.100 in 0.0810935468055
fun map getattr has run.100 in 0.0158168147069


La question est puis-je faire mieux que f5() ?

Par exemple comment puis-je appeler la built-in getattr avec un tuple d'argument (je pense à map(gettattr, zip(l,["x"]) ), qui ne marche pas tel quel.

Mes essais avec zip ou iterttools.starmap() ou .imap() m'ont fortement decu.

Dit autrement, comment combine-t'on les fonctions built-in intelligemment pour obtenir une classe de fonctions assez large ?


Merci d'avance