Как мне добавить лямбду к списку в Python? - PullRequest
1 голос
/ 12 апреля 2019

Я пытаюсь создать программу, которая создает список лямбда-функций в формате y=mx+b, где 'm' и 'b' - это заранее определенные значения

Моя общая цель - реализовать функцию , которая

  • Сфотографирует
  • Находит линии на нем
  • Распространение их по всей картине в сплошной цвет

По сути, что-то вроде Хафа преобразует , если вы знаете, что это такое.

Как только у меня появятся линии для определенного изображения, я могу создать лямбда-функцию для представления наклона линии и того, где она начинается. У меня проблема с невозможностью добавить лямбда-функцию в список.

Я пробовал это:

if __name__ == "__main__":
  nums = []
  for i in range(10):
    j = lambda x: x + i
    nums.append(j)
  for i in nums:
    print(i(1))

Вот ошибка, которую я получаю:

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'

Ответы [ 5 ]

2 голосов
/ 12 апреля 2019

Проблема в том, что создаваемые лямбды ссылаются на текущее значение i в активном кадре стека. Когда вы позже повторно используете i для второго цикла for, он будет связан с лямбдами в вашем списке. Когда вызывается как i(1), лямбда пытается вычислить 1 + i, где i - лямбда, поэтому, конечно, вы получите ошибку.

Вероятно, вам нужно заморозить значение i в момент, когда создается лямбда. Вы можете сделать это, заменив:

j = lambda x: x + i

с:

j = (lambda y: lambda x: x + y)(i)

Это эффективно фиксирует текущее значение i, связывая его с лямбда-переменной, а затем немедленно применяя эту лямбду, после чего привязка остается фиксированной.

1 голос
/ 12 апреля 2019

Это даст вам подсказку:

>>> i=1
>>> a=lambda x:x+i
>>> a(5)
6
>>> i=2
>>> a(5)
7

lambda использует i во внешней области видимости. В случае OP все функции одинаковы. Использование i в последнем цикле делает i функцией, а не целым числом. Измените его на что-то другое, и вы обнаружите, что все функции одинаковы, используя последнее значение i:

nums = []
for i in range(10):
    j = lambda x: x + i
    nums.append(j)
for f in nums:
    print(f(1))
10
10
10
10
10
10
10
10
10
10

Исправьте, сделайте i параметром для функции, чтобы зафиксировать значение как локальную переменную:

nums = []
for i in range(10):
    j = lambda x,i=i: x + i
    nums.append(j)
for f in nums:
    print(f(1))
1
2
3
4
5
6
7
8
9
10
0 голосов
/ 12 апреля 2019

Вы можете использовать operator.add и functools.partial и не использовать лямбду вообще:

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 голосов
/ 12 апреля 2019

Я думаю, вам нужно узнать больше о лямбда-функциях ... На самом деле, его синтаксис выглядит так: [ лямбда-аргументы: выражение ] Итак, проблема в том, что у вас есть две переменные в выражении, поэтому вам нужно передать два аргумента. Я не совсем понимаю, чего вы хотите достичь с помощью этой функции, но я думаю, вам нужно иметь два аргумента для m и b.

В вашем коде вам нужно инициализировать x и передать его в качестве аргумента лямбде.

            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 голосов
/ 12 апреля 2019

Ваше значение i изменилось, и это не то, что вы думаете.

Сначала вы создаете лямбду:

j = lambda x: x + i

в надежде, что я останусь как текущее значение (т. Е. 0, 1, 2 и т. Д.).

Тогда вы выполните это:

print(i(1))

Видите ли, как вы назвали свою вторую переменную итератора i ? Измените его на j , и ваш пример будет работать. Зачем? Поскольку python разрешает значение i в вашей лямбде, когда вы ее выполняете, а не когда вы ее определяете. Поэтому, когда вы выполните свою лямбду ( i (1) ), она перейдет к вашему лямбда-телу и попробует x + i . Тогда он будет искать i , который теперь содержит вашу лямбду (не INTEGER!). Отсюда твоя проблема.

Вам нужно сделать двойную функцию, чтобы она работала правильно. Попробуйте это:

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

Почему это работает? Когда вы вызываете generate_lambda , будет i переменная с вашим значением INTEGER. Это будет теневая переменная i , используемая позже для перебора лямбд. А поскольку вы никогда не изменяете переменную i внутри функции generate_lambda , она останется такой всегда.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...