Я вроде понимаю общее определение стековой памяти, кучи памяти, malloc, указателей и адресов памяти ... Я хотел бы немного комментировать и объяснить, в чем разница между ними ... [ 118] blockquote>
< = OK ...
Программа 1 выделяет память в стеке для переменной netWorth и использует указатель на этот адрес памяти стека для непосредственного изменения переменной netWorth. Это пример передачи по ссылке.
blockquote>< = Абсолютно правильно!
Q: Программа 2 ... Уничтожается ли локальная копия worthRef при возвращении?
blockquote>A:
int netWorth
существует только в области действия A (), включая вызов B ().Программа 1 и Программа 3 ... один передает указатель на переменную стека, а другой - на указатель на переменную кучи. Q: Но в этой ситуации зачем мне куча?
blockquote>A: Нет. Вполне нормально (возможно предпочтительнее ) просто взять addressof (& amp;) int, как вы это делали в программе 1.
Q: куча позволяет программисту выбирать время жизни переменной, верно?
blockquote>A: Да, это один из аспектов динамического выделения памяти. Вы правы.
В: Почему бы просто не сделать ее глобальной переменной в этом случае?
blockquote>A: Да, это еще одна альтернатива.
Ответ на любой вопрос "Почему стоит выбрать один вариант дизайна вместо другого?" обычно "это зависит".
Например, может быть, вы не можете просто объявить все «локальные переменные», потому что ваша среда имеет очень маленький, ограниченный стек. Это происходит:)
В общем,
Если вы можете объявить локальную переменную вместо выделения кучи, вам, как правило, следует.
Если вы можете избежать объявления глобальной переменной, вам, как правило, следует.
Я действительно не понимаю то, что конфликтует, Вы спрашиваете о, ни проблема с примером: хорошо иметь два сосуществования, независимые дескрипторы в тот же файл.
Одна вещь я не знал, что изучил в ответ на Ваш вопрос это, что существует новое завершение () метод на генераторах:
close()
повышает новоеGeneratorExit
исключение в генераторе для завершения повторения. При получении этого исключения код генератора должен или повыситьGeneratorExit
илиStopIteration
.
close()
назван, когда генератор собран "мусор", таким образом, это означает, что код генератора получает один последний шанс работать, прежде чем генератор будет уничтожен. Этот последний шанс означает этоtry...finally
операторы в генераторах, как могут теперь гарантировать, будут работать;finally
пункт будет теперь всегда получать шанс работать. Это походит на незначительный бит мелочей языка, но генераторы использования иtry...finally
на самом деле необходимо для реализацииwith
оператор описан PEP 343.http://docs.python.org/whatsnew/2.5.html#pep-342-new-generator-features
Таким образом, это обрабатывает ситуацию где a with
оператор используется в генераторе, но он уступает в середине, но никогда не возвращается — менеджер по контексту __exit__
метод назовут, когда генератор будет собран "мусор".
Править:
Относительно проблемы дескриптора файла: Я иногда забываю, что там существуют платформы, которые не подобны POSIX.:)
Насколько блокировки идут, я думаю, что Rafał Dowgird поражает голову в гвоздь, когда он говорит, что "Просто необходимо знать, что генератор точно так же, как любой другой объект, который содержит ресурсы". Я не думаю with
оператор действительно настолько релевантен здесь, так как эта функция страдает от тех же проблем мертвой блокировки:
def coroutine():
lock.acquire()
yield 'spam'
yield 'eggs'
lock.release()
generator = coroutine()
generator.next()
lock.acquire() # whoops!
Я не думаю, что существует реальный конфликт. Просто необходимо знать, что генератор точно так же, как любой другой объект, который содержит ресурсы, таким образом, это - обязанность создателя удостовериться, что он правильно завершен (и избегать конфликтов/мертвой блокировки с ресурсами, сохраненными объектом). Единственная (незначительная) проблема, которую я вижу здесь, состоит в том, что генераторы не реализуют протокол управления контекста (по крайней мере, с Python 2.5), таким образом, Вы не можете просто:
with coroutine() as cr:
doSomething(cr)
но вместо этого имейте к:
cr = coroutine()
try:
doSomething(cr)
finally:
cr.close()
Сборщик "мусора" делает close()
так или иначе, но это - плохая практика для доверия этому для освобождения ресурсов.
Поскольку yield
может выполнить произвольный код, я очень опасался бы держать блокировку по оператору урожая. Можно получить подобный эффект большим количеством других способов, тем не менее, включая вызов метода или функций, которые могли бы быть, были переопределены или иначе изменены.
Генераторы, однако, всегда (почти всегда) "закрыты", любой с явным close()
звоните, или только будучи собранным "мусор". Закрытие генератора бросает a GeneratorExit
исключение в генераторе и следовательно выполняет наконец пункты, с очисткой оператора, и т.д. Можно поймать исключение, но необходимо бросить или выйти из функции (т.е. бросить a StopIteration
исключение), вместо того, чтобы уступить. Это - вероятно, плохая практика для доверия сборщику "мусора" для закрытия генератора в случаях как, Вы записали, потому что это могло произойти позже, чем Вы могли бы хотеть, и если кто-то называет sys. _ выход (), затем Вашей очистки не могло бы произойти вообще.
Это было бы то, как я ожидал вещи работать. Да, блок не высвободит свои средства, пока он не завершится, таким образом, в этом смысле ресурс вышел, это - лексическое вложение. Однако, но это не отличается от создания вызова функции, который пытался использовать тот же ресурс в с блоком - ничто не помогает Вам в случае, где блок еще не завершился по любой причине. Это - действительно ничего характерного для генераторов.
Одна вещь, которую могло бы стоить взволновать о том, хотя поведение, если генератор никогда не возобновляется. Я ожидал бы with
блок для действия как a finally
блок и вызов __exit__
часть после завершения, но это, кажется, не имеет место.