режим отложенной загрузки Python использует последнее значение в цикле - PullRequest
0 голосов
/ 01 июля 2019

Я хочу установить методы класса в цикле.Вот мой пример кода:

class A:
    pass

def gen_func(k):
    return classmethod(lambda cls: k)

for k in ('m1', 'm2'):
    def gen_func2(k):
        return classmethod(lambda cls: k)
    setattr(A, 'resolve_%s'%k, classmethod(lambda cls: k))  # print result is: m2, m2
    # setattr(A, 'resolve_%s'%k, classmethod((lambda: lambda cls: k)()))  # print result is: m2, m2

    # setattr(A, 'resolve_%s'%k, gen_func2(k)) # print result is: m1, m2
    # setattr(A, 'resolve_%s'%k, gen_func(k))  # print result is: m1, m2 #OK#

print(A.resolve_m1()) # expected print --> m1
print(A.resolve_m2()) # expected print --> m2

Ожидаемый результат print m1, m2.

Но когда я генерирую метод в областях цикла, k всегда является последним:m2.

Я только знаю, что это причина scope, если мы используем функцию в цикле, она выполняется лениво.

И я определяю gen_func внециклы, это сработало.

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

Я пытался найти причину по книгам или веб-сайту, но понятия не имею об этом.

1 Ответ

0 голосов
/ 01 июля 2019

Спасибо, @ AndrejKesely

Теперь я знаю, что это такое, вы можете написать с помощью лямбды:

python link

setattr(A, 'resolve_%s'%k, classmethod((lambda k: lambda cls: k)(k)))

Здесь введение js-замыканий , есть несколько картинок, которые полезны для понимания процесса замыканий:

Эта концепция объекта области очень отличается от, скажем, C илиC ++, где локальные переменные хранятся в стеке.В JavaScript вместо этого объекты области видимости размещаются в куче (или, по крайней мере, они ведут себя так), поэтому они могут остаться выделенными, даже если функция уже возвращена.Подробнее об этом позже.

...