2014-07-23 4 views
0

Si je définir une fonction:Fonction avec des listes comme arguments/scalaires

def somefunc(a, b, c): 
    out = [ (a+b)/c for a, b, c in zip(a, b, c) ] 
    return out 

tous les arguments doivent être des listes de la même longueur, sinon je recevrais la sortie tronquée. Exemple: somefunc([1, 2], [3, 4], [5, 5]) me donnerait [0.8, 1.2].

Il serait vraiment pratique de pouvoir entrer un seul nombre au lieu d'une liste quand il ne change pas, comme: somefunc([1, 2], [3, 4], 5). Bien sûr, l'un des arguments peut être réduit à une seule valeur au lieu d'une liste. Ceci peut être réalisé en utilisant numpy avec cette définition de fonction:

from numpy import array 

def somefunc(a, b, c): 

    a=array(a) 
    b=array(b) 
    c=array(c) 

    out = (a+b)/c 
    return out 

est-il un moyen de faire la même chose sans numpy (et sans convertir tous les arguments un par un)?

+0

Non, 'zip' attend des arguments itérables; Si votre fonction prend des arguments non-iterables, vous devrez les convertir. – jonrsharpe

+0

Note: Si vous voulez des fonctionnalités NumPy, le plus simple sera d'utiliser NumPy. Chaque fonctionnalité peut bien sûr être implémentée sans NumPy, mais si cela était facile, NumPy ne serait pas là. – user2357112

Répondre

2

Bien sûr, vous pouvez créer une liste infinie en répétant tout argument qui n'est pas une liste en soi. Numpy est génial, et est parfait pour la vectorisation des calculs comme celui que vous avez publié.

from itertools import repeat 

def broadcast(o): 
    return o if hasattr(o, '__iter__') else repeat(o) 

def somefunc(a, b, c): 
    out = [ (a+b)/c for a, b, c in zip(broadcast(a), broadcast(b), broadcast(c)) ] 
    return out 

>>> somefunc([1, 2], [3, 4], 5) 
[0.8, 1.2] 
>>> somefunc([1, 2], 5, [3, 4]) 
[2.0, 1.75] 
>>> 
+0

Ok, mais cela ne fonctionne pas si l'argument scalaire n'est pas le dernier: 'somefunc ([1, 2], 3, [5, 5])' – gaggio

+0

Je pense que vous avez commenté la mauvaise réponse. La solution de rroowwllaanndd ne fonctionne pas si l'un des deux premiers arguments est scalaire. Le mien fait. –

+0

ooops vous avez raison, mais maintenant l'autre a été édité et cela fonctionne aussi bien. Merci – gaggio

1

Je vous recommande faire l'utiliser.

De même, vous n'avez pas besoin de convertir tous les arguments en tableaux, un seul, et il est préférable d'utiliser asarray, ce qui éviterait de créer une nouvelle copie lorsque cela n'est pas nécessaire.

def somefunc(a, b, c): 
    return (asarray(a) + b)/c