Действительно ли безопасно уступить из “с” блоком в Python (и почему)?

Я вроде понимаю общее определение стековой памяти, кучи памяти, malloc, указателей и адресов памяти ... Я хотел бы немного комментировать и объяснить, в чем разница между ними ... [ 118]

< = OK ...

Программа 1 выделяет память в стеке для переменной netWorth и использует указатель на этот адрес памяти стека для непосредственного изменения переменной netWorth. Это пример передачи по ссылке.

< = Абсолютно правильно!

Q: Программа 2 ... Уничтожается ли локальная копия worthRef при возвращении?

A: int netWorth существует только в области действия A (), включая вызов B ().

Программа 1 и Программа 3 ... один передает указатель на переменную стека, а другой - на указатель на переменную кучи. Q: Но в этой ситуации зачем мне куча?

A: Нет. Вполне нормально (возможно предпочтительнее ) просто взять addressof (& amp;) int, как вы это делали в программе 1.

Q: куча позволяет программисту выбирать время жизни переменной, верно?

A: Да, это один из аспектов динамического выделения памяти. Вы правы.

В: Почему бы просто не сделать ее глобальной переменной в этом случае?

A: Да, это еще одна альтернатива.

Ответ на любой вопрос "Почему стоит выбрать один вариант дизайна вместо другого?" обычно "это зависит".

Например, может быть, вы не можете просто объявить все «локальные переменные», потому что ваша среда имеет очень маленький, ограниченный стек. Это происходит:)

В общем,

  1. Если вы можете объявить локальную переменную вместо выделения кучи, вам, как правило, следует.

  2. Если вы можете избежать объявления глобальной переменной, вам, как правило, следует.

43
задан cdleary 26 March 2009 в 10:31
поделиться

4 ответа

Я действительно не понимаю то, что конфликтует, Вы спрашиваете о, ни проблема с примером: хорошо иметь два сосуществования, независимые дескрипторы в тот же файл.

Одна вещь я не знал, что изучил в ответ на Ваш вопрос это, что существует новое завершение () метод на генераторах:

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!
22
ответ дан Miles 26 November 2019 в 23:10
поделиться

Я не думаю, что существует реальный конфликт. Просто необходимо знать, что генератор точно так же, как любой другой объект, который содержит ресурсы, таким образом, это - обязанность создателя удостовериться, что он правильно завершен (и избегать конфликтов/мертвой блокировки с ресурсами, сохраненными объектом). Единственная (незначительная) проблема, которую я вижу здесь, состоит в том, что генераторы не реализуют протокол управления контекста (по крайней мере, с Python 2.5), таким образом, Вы не можете просто:

with coroutine() as cr:
  doSomething(cr)

но вместо этого имейте к:

cr = coroutine()
try:
  doSomething(cr)
finally:
  cr.close()

Сборщик "мусора" делает close() так или иначе, но это - плохая практика для доверия этому для освобождения ресурсов.

9
ответ дан Rafał Dowgird 26 November 2019 в 23:10
поделиться

Поскольку yield может выполнить произвольный код, я очень опасался бы держать блокировку по оператору урожая. Можно получить подобный эффект большим количеством других способов, тем не менее, включая вызов метода или функций, которые могли бы быть, были переопределены или иначе изменены.

Генераторы, однако, всегда (почти всегда) "закрыты", любой с явным close() звоните, или только будучи собранным "мусор". Закрытие генератора бросает a GeneratorExit исключение в генераторе и следовательно выполняет наконец пункты, с очисткой оператора, и т.д. Можно поймать исключение, но необходимо бросить или выйти из функции (т.е. бросить a StopIteration исключение), вместо того, чтобы уступить. Это - вероятно, плохая практика для доверия сборщику "мусора" для закрытия генератора в случаях как, Вы записали, потому что это могло произойти позже, чем Вы могли бы хотеть, и если кто-то называет sys. _ выход (), затем Вашей очистки не могло бы произойти вообще.

1
ответ дан Doug 26 November 2019 в 23:10
поделиться

Это было бы то, как я ожидал вещи работать. Да, блок не высвободит свои средства, пока он не завершится, таким образом, в этом смысле ресурс вышел, это - лексическое вложение. Однако, но это не отличается от создания вызова функции, который пытался использовать тот же ресурс в с блоком - ничто не помогает Вам в случае, где блок еще не завершился по любой причине. Это - действительно ничего характерного для генераторов.

Одна вещь, которую могло бы стоить взволновать о том, хотя поведение, если генератор никогда не возобновляется. Я ожидал бы with блок для действия как a finally блок и вызов __exit__ часть после завершения, но это, кажется, не имеет место.

0
ответ дан Brian 26 November 2019 в 23:10
поделиться
Другие вопросы по тегам:

Похожие вопросы: