J'essaie de créer un programme qui crée une liste de fonctions lambda au format y = mx + b
, où «m» et «b» sont des valeurs prédéterminées
Mon objectif général est de mettre en œuvre une fonction qui
Fondamentalement, quelque chose comme une transformation Hough si vous savez ce que c'est.
Une fois que j'ai les lignes pour une image spécifique, je peux créer un lambda fonction pour représenter la pente de la ligne et son point de départ. Je rencontre un problème pour ne pas pouvoir ajouter une fonction lambda à la liste.
J'ai essayé ceci:
Traceback (most recent call last): File "C:/Users/me/.PyCharmCE2018.3/config/scratches/scratch_3.py", line 7, in <module> print(i(1)) File "C:/Users/me/.PyCharmCE2018.3/config/scratches/scratch_3.py", line 4, in <lambda> j = (lambda x: x + i) TypeError: unsupported operand type(s) for +: 'int' and 'function'
Voici l'erreur que j'obtiens:
if __name__ == "__main__": nums = [] for i in range(10): j = lambda x: x + i nums.append(j) for i in nums: print(i(1))
p>
5 Réponses :
Le problème est que les lambdas que vous créez font référence à la valeur actuelle de i
dans le cadre de pile actif. Lorsque vous réutilisez plus tard i
pour la deuxième boucle for
, il est lié aux lambdas de votre liste. Lorsqu'il est invoqué en tant que i (1)
, les lambdas essaient d'évaluer 1 + i
où i
est le lambda, donc bien sûr vous obtenez un
Ce que vous voulez probablement, c'est geler la valeur de i
au point où le lambda est créé. Vous pouvez le faire en remplaçant:
j = (lambda y: lambda x: x + y)(i)
par:
j = lambda x: x + i
Cela capture efficacement la valeur actuelle de i
en le liant à une variable lambda, puis en appliquant immédiatement ce lambda, après quoi la liaison reste fixe.
Ou lambda x, i = i: x + i
@jonrsharpe Oui, je pense que cela fonctionnerait également, même si cela permettrait de passer un deuxième argument qui remplace la valeur capturée de i
.
ok je ne veux pas paraître stupide mais comment pourrais-je appliquer cela à un lambda qui a besoin de 2 variables? comme ma fonction mx + b, où x est la chose qui change, et b et m sont déjà déclarés mais changeront à chaque itération dans la boucle for?
Par exemple, si vous souhaitez capturer 3 valeurs, dites i1
, i2
et i3
, alors vous pouvez faire: j = (lambda y1, y2, y3: lambda x: x + y1 + y2 + y3) (i1, i2, i3)
. Bien sûr, vous pouvez faire ce que vous voulez avec eux dans le lambda intérieur, mais vous voyez l'idée.
`` `si nom ==" main ": nums = [] j = 0 pour i dans l'intervalle (10): j + = 1 H = (lambda y: lambda x: y) (j) L = (lambda y: lambda x: H (x) + y) (i) nums.append (L) for i in nums: print (i (1))
Cela vous donnera un indice:
1 2 3 4 5 6 7 8 9 10
lambda
utilise i dans la portée externe. Dans le cas OP, toutes les fonctions sont les mêmes. L'utilisation de i
dans la boucle finale fait de i
une fonction, pas un entier. Changez-le en autre chose, et vous constaterez que les fonctions sont toutes les mêmes, en utilisant la dernière valeur de i
:
nums = [] for i in range(10): j = lambda x,i=i: x + i nums.append(j) for f in nums: print(f(1))
10 10 10 10 10 10 10 10 10 10
Le correctif est de faire de i
un paramètre de la fonction, pour capturer la valeur en tant que variable locale:
nums = [] for i in range(10): j = lambda x: x + i nums.append(j) for f in nums: print(f(1))
>>> i=1 >>> a=lambda x:x+i >>> a(5) 6 >>> i=2 >>> a(5) 7
est ce paramètre par défaut? manière intelligente :)
Wow, c'est assez sournois. Je l'aime. merci beaucoup pour la réponse au fait!
Votre valeur de i a changé et ce n'est pas ce que vous pensez.
D'abord, vous créez lambda:
if __name__ == "__main__": nums = [] for i in range(10): def generate_lambda(i): return lambda x: x + i j = generate_lambda(i) nums.append(j) for i in nums: print(i(1))
en espérant que je resterai comme valeur ACTUELLE (donc 0, 1, 2 et ainsi de suite).
Ensuite, vous l'exécutez:
print(i(1))
Voyez-vous, comment vous avez nommé votre deuxième variable d'itérateur i ? Changez-le en j et votre exemple fonctionnera. Pourquoi? Parce que python résout la valeur de i dans votre lambda, lorsque vous l'exécutez, pas lorsque vous le définissez. Ainsi, lorsque vous exécutez votre lambda ( i (1) ), il ira dans votre corps lambda et essaiera x + i . Ensuite, il recherchera i , qui contient maintenant votre lambda (et non le INTEGER!). D'où votre problème.
Vous devez faire une double fonction pour que cela fonctionne correctement. Essayez ceci:
j = lambda x: x + i
Pourquoi cela fonctionne-t-il? Lorsque vous appelez generate_lambda , il y aura une variable i avec votre valeur INTEGER. Il observera la variable i utilisée plus tard pour itérer sur les lambdas. Et comme vous ne modifiez jamais la variable i dans la fonction generate_lambda , elle restera comme ça pour toujours.
Je pense que vous devez en savoir plus sur les fonctions lambda ... En fait, sa syntaxe est comme: [ arguments lambda: expression ] Donc, le problème est que vous avez deux variables dans l'expression, vous devez donc passer deux arguments. Je n'obtiens pas vraiment ce que vous voulez obtenir avec cette fonction, mais je suppose que vous devez avoir deux arguments pour m et b.
Dans votre code, vous devez initialiser x et le passer comme argument à lambda.
nums = [] x=0 for i in range(10): j = lambda x,i : x + i nums.append(j) for i in nums: print(i(1,1))
Vous pouvez utiliser operator.add et functools.partial et ne pas lambda du tout:
import operator import functools if __name__ == "__main__": nums = [] for i in range(10): nums.append(functools.partial(operator.add, i)) for i in nums: print(i(1))
Regardez ici: book.pythontips.com/en/latest/lambdas.html
donc j'ai regardé ce site et en gros j'ai essayé de changer le "i" en "1" et cela a bien fonctionné. pourquoi est-ce que je peux utiliser "i" à la place? pour mon vrai projet, j'ai en quelque sorte besoin d'une variable modifiable.
Voir sopython.com/canon/30/...
Double-possible de Portée des fonctions lambda et leurs paramètres?