Как правильно настроить динамически определенные глобальные функции в цикле? [Дубликат]

Решение: 1. sudo apt remove python-pip 2. pip3 install pip (или установите pip с помощью get-pip.py )

Почему: Эта ошибка произошла в pip 8.0.1 который установлен apt-get. И произошло, только когда ваша сеть нестабильна.

Если у вас есть pip, установленный с apt, он скрывает пип, который вы установили другими способами, поэтому сначала вы должны удалить apt one.

Я отключил сеть и протестировал 8.0.1, 9.0.3, 10.x 3 версии, установленные с pip3 или get-pip.py, при этом не было ошибок. & nbsp; & nbsp; Итак, я думаю, что только apt версия pip 8.0.1 имеет эту ошибку, другие - в порядке.

36
задан FunkySayu 14 October 2015 в 06:54
поделиться

3 ответа

Вам нужно связать d для каждой созданной функции. Один из способов сделать это - передать его как параметр со значением по умолчанию:

lambda d=d: self.root.change_directory(d)

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

lambda bound_d=d: self.root.change_directory(bound_d)

Помните, как работают значения по умолчанию, например, для изменяемых объектов, таких как списки и dicts, потому что вы привязываете объект.

Эта идиома параметров с значениями по умолчанию достаточно распространены, но может быть неудачным, если вы исследуете параметры функции и определяете, что делать в зависимости от их присутствия. Вы можете избежать параметра с другим закрытием:

(lambda d=d: lambda: self.root.change_directory(d))()
# or
(lambda d: lambda: self.root.change_directory(d))(d)

. Еще лучше, редизайн того, как вы обрабатываете «команды», поможет здесь и должен помочь в другом месте.

48
ответ дан Roger Pate 20 August 2018 в 06:56
поделиться
  • 1
    Я не знал, что в lambdas допустимы значения по умолчанию. Передача лямбда с аргументом по умолчанию в качестве аргумента ключевого слова выглядит просто странно: command = lambda path = path: selected(path). – ArtOfWarfare 15 January 2016 в 15:28

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

foo = lambda d: lambda : self.root.change_directory(d)
for d in directorys:
    self.command["cd " + d] = (foo(d))
0
ответ дан MonsterBat Doppelgänger 20 August 2018 в 06:56
поделиться

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

Для более простого примера:

funcs = []
for x in [1,2,3]:
  funcs.append(lambda: x)

for f in funcs:
  print f()

# output:
3
3
3

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

def makeFunc(x):
  return lambda: x

funcs = []
for x in [1,2,3]:
  funcs.append(makeFunc(x))

for f in funcs:
  print f()

# output:
1
2
3

Вы также можете зафиксировать область видимости внутри выражения лямбда

lambda bound_x=x: bound_x

. Однако в целом это не очень хорошая практика, поскольку вы изменили подпись своей функции.

14
ответ дан robbie_c 20 August 2018 в 06:56
поделиться
Другие вопросы по тегам:

Похожие вопросы: