2
votes

Comment ajouter un lambda à une liste en python?

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

  • Prend une photo
  • Recherche les lignes dessus
  • Les étend sur toute l'image dans une couleur unie

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>


4 commentaires

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?


5 Réponses :


5
votes

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 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.


5 commentaires

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))



2
votes

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


2 commentaires

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!



0
votes

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.


0 commentaires

0
votes

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))


0 commentaires

0
votes

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))


0 commentaires