Когда Вы пишете [x]*3
, Вы получаете, по существу, список [x, x, x]
. Таким образом, список с 3 ссылками на тот же x
. Когда Вы тогда изменяете этот сингл x
, это видимо через все три ссылки на него.
Для фиксации его необходимо удостовериться, что Вы создаете новый список в каждом положении. Один способ сделать это
[[1]*4 for _ in range(3)]
, который переоценит [1]*4
каждый раз вместо того, чтобы оценить его однажды и сделать 3 ссылки на 1 список.
Вы могли бы задаться вопросом, почему *
не может сделать независимые объекты путем, понимание списка делает. Поэтому оператор умножения *
воздействует на объекты, не видя выражения. Когда Вы используете *
для умножения [[1] * 4]
на 3, *
только видит, что список с 1 элементом [[1] * 4]
оценивает к, не [[1] * 4
текст выражения. *
понятия не имеет, как сделать копии того элемента, никакая идея, как переоценить [[1] * 4]
, и никакая идея, Вы даже хотите копии, и в целом, даже не могло бы быть способа скопировать элемент.
единственная опция *
имеет, должен сделать новые ссылки на существующий подсписок вместо того, чтобы пытаться сделать новые подсписки. Что-либо еще было бы непоследовательно или потребовало бы основного перепроектирования фундаментальных проектных решений языка.
Напротив, понимание списка переоценивает выражение элемента на каждом повторении. [[1] * 4 for n in range(3)]
переоценивает [1] * 4
, каждый раз по той же причине [x**2 for x in range(3)]
переоценивает x**2
каждый раз. Каждая оценка [1 120] генерирует новый список, таким образом, понимание списка делает то, что Вы хотели.
Кстати, [1] * 4
также не копирует элементы [1 122], но это не имеет значения, так как целые числа неизменны. Вы не можете сделать чего-то как [1 123] и превратить 1 в 2.
Стек используется в основном во время вызова функции, но в зависимости от языка и уровня программирования он может использоваться для временного хранения данных регистров процессора или других переменных.
Кроме того, стек также можно использовать для краткосрочного крупномасштабного хранения данных при использовании рекурсивных функций , которые сохраняют частичные данные в стеке и вызывают себя снова.
Общее использование стека для,
И, да, стек также используется для эксплойтов .
Его природа передачи адреса возврата туда, где вызываемая функция возвращается обратно,
в сочетании со слабостью проверки границ массива в языке C
дает очень
хороший способ вызвать переполнение буфера в стеке уязвимой (небезопасно написанной) программы.
Это зависит от микропроцессора. Обычно его роль заключается в хранении локальных переменных и параметров функций.
И на самом деле это не микропроцессор, а центральная память.
Некоторые микропроцессоры имеют стековых регистров для повышения эффективности, см. Статью SPARC в Википедии; у других есть микростек для микропрограмм ... Фактически, это очень широкий термин.
На самом низком уровне стек - это место, где определенные инструкции сохраняют или извлекают данные и где данные сохраняются при возникновении прерывания. Микропроцессоры различаются, но существует 5 общих типов специфичных для стека инструкций:
Когда происходит прерывание процессора (из-за внешнего устройства), CPU сохраняет текущий счетчик программы и (обычно) регистр флагов в стеке и переходит к подпрограмме обработки. Это позволяет подпрограмме обработки обрабатывать прерывание и возвращаться к тому, что делал ЦП, с сохранением текущего состояния.
В то время как микропроцессор имеет только один активный стек за раз, операционная система может создать впечатление, что есть несколько стеки. По крайней мере, один для ОС, по одному для каждого процесса и по одному для каждого потока. Фактически, сами потоки могут реализовывать несколько стеков.
На более высоком уровне, какой бы язык ни использовался для реализации потока, он часто будет использовать стек в своих целях для хранения параметров функционального вызова, локальных переменных и возвращаемых значений вызова функций ( говоря здесь в общих чертах - обратитесь к низкоуровневой документации вашего языка для конкретных деталей).
На этом я завершаю свое восходящее объяснение стека.
В то время как микропроцессор имеет только один активный стек одновременно, операционная система может создать впечатление, что существует несколько стеков. По крайней мере, один для ОС, по одному для каждого процесса и по одному для каждого потока. Фактически, сами потоки могут реализовывать несколько стеков.
На более высоком уровне, какой бы язык ни использовался для реализации потока, он часто будет использовать стек в своих целях для хранения параметров функционального вызова, локальных переменных и возвращаемых значений вызова функций ( говоря здесь в общих чертах - обратитесь к низкоуровневой документации вашего языка для конкретных деталей).
На этом я завершаю свое восходящее объяснение стека.
В то время как микропроцессор имеет только один активный стек одновременно, операционная система может создать впечатление, что существует несколько стеков. По крайней мере, один для ОС, по одному для каждого процесса и по одному для каждого потока. Фактически, сами потоки могут реализовывать несколько стеков.
На более высоком уровне, какой бы язык ни использовался для реализации потока, он часто будет использовать стек в своих целях для хранения параметров функционального вызова, локальных переменных и возвращаемых значений вызова функций ( говоря здесь в общих чертах - обратитесь к низкоуровневой документации вашего языка для конкретных деталей).
На этом я завершаю свое восходящее объяснение стека.
На самом деле стек не является терминологией для процессора, он используется для обычного вызова языка. Подпрограмма может использовать стек для получения параметров и сохранения локальных переменных, а также вызывать другие подпрограммы.
Стек используется для хранения и получения адресов возврата во время вызовов функций. Его хорошо используют во время вызовов вложенных функций или рекурсивных вызовов функций. Он также используется для передачи аргументов функции .
На микропроцессоре он также используется для хранения содержимого регистра состояния перед переключением контекста.
приветствует
]http://www.hobbyprojects.com/microprocessor_systems/images/stack.gif
Стек является временным хранилищем данных.
ЦП может ЗАПИСАТЬ важные данные в стек, пока он обрабатывает другие данные.
Когда он завершает эту задачу, он ВЫТЯНИТ сохраненные данные из стека.
Это похоже на стопку тарелок. Нижняя пластина - это первый бит данных, помещенный в стек. Верхняя пластина - это последние данные, которые нужно отправить. Верхняя пластина вытягивается первой, а нижняя пластина - последние данные, которые нужно снимать. Это стек ПОСЛЕДНИЙ ВХОД, ПЕРВЫЙ ВЫХОД.
На диаграммах сначала помещается X, затем Y и, наконец, A. ЦП уходит для обработки других данных. По завершении этой задачи он возвращается, чтобы извлечь сохраненные данные. Сначала извлекается A, затем Y и, наконец, X.
Команда для передачи данных - PHA. В стек могут быть помещены только данные из аккумулятора. Другие данные могут быть отправлены, если они сначала передаются в аккумулятор.
Команда для извлечения данных из стека - PLA. Данные из стека передаются в аккумулятор.
Стек 6502 состоит из 256 байт и занимает страницу 1, адреса с 256 по 511.
Просто Чтобы добавить к некоторым из этих ответов, некоторые младшие микросхемы, такие как линия PIC, имеют стек вызовов аппаратный , что означает, что он не может быть динамически распределен, как на аппаратном уровне.
Следствием этого является то, что вы можете выполнить только определенное количество вызовов функций, прежде чем у вас закончится стек; это, конечно, верно и для программного обеспечения, но часто аппаратный стек может быть очень ограниченным и может потребовать от вас переосмысления вашей программы, чтобы «сгладить» вызовы функций.