Вот список дополнительных подходов:
Дан
import itertools as it
import collections as ct
import more_itertools as mit
iterable = range(11)
n = 3
Код
Стандартная библиотека
list(it.zip_longest(*[iter(iterable)] * n))
# [(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, None)]
d = {}
for i, x in enumerate(iterable):
d.setdefault(i//n, []).append(x)
list(d.values())
# [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10]]
dd = ct.defaultdict(list)
for i, x in enumerate(iterable):
dd[i//n].append(x)
list(dd.values())
# [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10]]
more_itertools
+ sup>
list(mit.chunked(iterable, n))
# [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10]]
list(mit.sliced(iterable, n))
# [range(0, 3), range(3, 6), range(6, 9), range(9, 11)]
list(mit.grouper(n, iterable))
# [(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, None)]
list(mit.windowed(iterable, len(iterable)//n, step=n))
# [(0, 1, 2), (3, 4, 5), (6, 7, 8), (9, 10, None)]
Список литературы
zip_longest
( связанный пост , соответствующий пост ) setdefault
(упорядоченные результаты требуют Python 3.6 +) collections.defaultdict
(упорядоченные результаты требуют Python 3.6 +) more_itertools.chunked
( связанный пост ) more_itertools.sliced
more_itertools.grouper
( соответствующий пост ) more_itertools.windowed
(см. Также stagger
, zip_offset
) + sup> Сторонняя библиотека, в которой реализованы рецепты itertools и другие. > pip install more_itertools
Нет возможности установить это поведение, но есть модуль "strict", поставляемый со стандартной установкой, который делает именно это (путем изменения мета-таблиц). Использование: require 'strict'
Для получения более подробной информации и других решений: http://lua-users.org/wiki/DetectingUndefinedVariables , но я рекомендую 'strict'.
«Локальное по умолчанию неверно ». См.
http://lua-users.org/wiki/LocalByDefault
http://lua-users.org/wiki/LuaScopingDiscussion
Вам необходимо использовать какую-то глобальную защиту окружающей среды. Для этого есть несколько статических инструментов (не слишком зрелых), но наиболее распространенным решением является использование защиты во время выполнения, основанной на __ index
и __ newindex
в _G
метатаблица.
плагин Shameles: эта страница также может быть полезна:
http://code.google.com/p/lua-alchemy/wiki/LuaGlobalEnvironmentProtection
Обратите внимание, что пока обсуждается Lua, встроенный в swf, описанный метод (см. источники ) действительно работает для общего Lua. Мы используем что-то подобное в нашем производственном коде на работе.
На самом деле, дополнительной глобальной переменной с устаревшей ссылкой на корабль будет достаточно, чтобы GC не отбросил объект. Таким образом, его можно было обнаружить во время выполнения, заметив, что корабль теперь «мертв», и отказавшись что-либо с ним делать. Это все еще не тот корабль, но, по крайней мере, вы не разбились.
Вы можете сделать одно - хранить пользовательские сценарии в песочнице , возможно, в песочнице для каждого сценария. При правильном изменении таблицы окружения песочницы или ее метатаблицы вы можете организовать удаление всех или большинства глобальных переменных из песочницы до (или сразу после) вызова кода пользователя.
Очистка песочницы после вызовов будет иметь то преимущество, что отбрасывает лишние ссылки на вещи, которые не должны торчать. Это можно сделать, сохранив белый список полей, которым разрешено оставаться в среде, и удалив все остальные.
Например, следующий код реализует изолированный вызов пользовательской функции со средой, содержащей только имена из белого списка, за новой рабочей таблицей, предоставляемой для каждого вызова.
-- table of globals that will available to user scripts local user_G = { print=_G.print, math=_G.math, -- ... } -- metatable for user sandbox local env_mt = { __index=user_G } -- call the function in a sandbox with an environment in which new global -- variables can be created and modified but they will be discarded when the -- user code completes. function doUserCode(user_code, ...) local env = setmetatable({}, env_mt) -- create a fresh user environment with RO globals setfenv(user_code, env) -- hang it on the user code local results = {pcall(user_code, ...)} setfenv(user_code,{}) return unpack(results) end
Это может быть расширено, чтобы сделать глобальную таблицу читаемой. -только отодвинув его назад за еще один доступ с метатегией, если хотите.
Обратите внимание, что полное решение для песочницы также должно учитывать, что делать с пользовательским кодом, который случайно (или злонамеренно) выполняет бесконечный (или просто очень длинный) цикл или другую операцию. Общие решения для этого - случайная тема для обсуждения в списке Lua , но найти хорошие решения сложно.
Сорта.
В Lua глобальные объекты условно находятся в таблице глобальных объектов _G
(на самом деле все немного сложнее, но со стороны Lua нет возможности скажите AFAIK). Как и в случае со всеми другими таблицами Lua, можно присоединить метатаблицу __ newindex
к _G
, которая контролирует, как к ней добавляются переменные. Позвольте этому обработчику __ newindex
делать все, что вы хотите, когда кто-то создает глобал: выдает ошибку, разрешает, но выводит предупреждение и т. Д.
Чтобы вмешаться в _G
, это Самый простой и понятный в использовании setfenv
. См. Документацию .