Постановка проблемы:
Как мне создать функцию, которая будет передавать значение, определенное при создании функции, а не при ее вызове?
Фон
Используя altair
Я пытаюсь настроить несколько тем, и для создания темы мне нужно «зарегистрировать» it с кодом примерно так:
def black_marks():
return {
'config': {
'mark': {
'color': 'black',
'fill': 'black'
}
}
}
# register the custom theme under a chosen name
alt.themes.register('black_marks', black_marks)
# enable the newly registered theme
alt.themes.enable('black_marks')
На этом этапе, поскольку 'black_marks'
- это и registerd , и включен , любое будущее использование altair
будет включать эти значения по умолчанию.
Обратите внимание, что функция black_marks
возвращает dict
, и именно функцию необходимо зарегистрировать .
Проблема
У меня есть несколько тем, которые я хотел бы настроить сразу, поэтому я создал al oop с помощью этих конфигураций в моем коде примерно так:
for theme_name, theme_dict in mythemes.items():
themes.register(theme_name, lambda: theme_dict)
Затем я обнаружил, что темы фактически не зарегистрированы в то время, когда вызывается функция themes.register
. Вместо этого он обрабатывается «лениво».
Например, допустим, что ключи темы: ['light', 'dark', 'paper']
. Завершив l oop выше, я обнаружил, что все 3 из этих имен тем зарегистрированы (я могу alt.themes.enable('light')
, например), но все они указывают на последнюю. , paper
. Это происходит потому, что theme_dict
в последнем раунде действительно указывает на тему, связанную с paper
.
Desire
Я бы хотел иметь возможность каким-то образом «жестко закодировать» то, на что указывает theme_dict
, чтобы themes.register
указывал на функцию, которая содержит сгенерированный dict на каждом проходе. Но как бы я ни пытался об этом думать, я не могу заставить лямбда-функцию создать функцию, которая «высечена в камне». Вместо этого функция просто вернет все, что было на последней итерации.
Итак, хотя это своего рода проблема altair
-specifi c, я чувствую, что решение должно быть общим c одним:
Как мне создать функцию, которая будет передавать значение, которое определяется при создании функции, а не при вызове функции?
Полный пример
Согласно просьбе в комментарии, вот более полный снимок моего кода:
for theme_key, theme_file in THEME_FILES.items(): # THEME_FILES is a dictionary with values containing file paths
with open(theme_file) as theme_fh:
raw_theme = toml.load(theme_fh)
dims = {
"width": raw_theme.pop("width"),
"height": raw_theme.pop("height"),
}
raw_theme["view"] = dims
final_theme["config"] = raw_theme
themes.register(theme_key, lambda: final_theme)
(Извинения за плохие имена переменных ... Я был разочарован проблемы, которые у меня были, и переименование, думая, что проблема была случайной перезаписью глобальных переменных.)
Опять же, для ясности, theme_key
правильно зарегистрирован. Если, например, разные ключи были ['light', 'dark', 'paper']
, то я могу видеть все 3. Но все три указывают на тему, созданную на последней итерации. В данном случае это тема 'paper'
.
Если бы я просто перебрал одну из тем, она работала бы отлично. Так что я почти уверен, что определил проблему.