Одноразовый, завернутый в оператор using, добавляется в список, но все равно доступен через список извне инструкции using. Зачем? [Дубликат]

Я думаю, что ответ на этот вопрос заключается в том, как python передает данные в параметр (передать по значению или по ссылке), а не изменчивость или как питон обрабатывает инструкцию «def».

Краткое введение. Во-первых, в питоне есть два типа типов данных: один простой элементарный тип данных, например числа, а другой тип данных - объекты. Во-вторых, при передаче данных в параметры python передает элементарный тип данных по значению, т. Е. Делает локальную копию значения локальной переменной, но передает объект по ссылке, т. Е. Указывает на объект.

Признавая вышеуказанные два момента, давайте объясним, что произошло с кодом python. Это происходит только из-за передачи по ссылке для объектов, но не имеет ничего общего с mutable / immutable или, возможно, факта, что оператор «def» выполняется только один раз, когда он определен.

[] является объектом , поэтому python передает ссылку [] на a, т. е. a является только указателем на [], который лежит в памяти как объект. Существует только одна копия [] с, однако, многими ссылками на нее. Для первого foo () список [] изменен на 1 методом добавления. Но учтите, что существует только одна копия объекта списка, и этот объект теперь становится 1 . При запуске второго foo (), какая веб-страница effbot говорит (элементы больше не оцениваются) неверна. a оценивается как объект списка, хотя теперь содержимое объекта 1 . Это эффект прохождения по ссылке! Результат foo (3) может быть легко получен таким же образом.

Чтобы еще раз подтвердить мой ответ, давайте рассмотрим два дополнительных кода.

===== = № 2 ========

def foo(x, items=None):
    if items is None:
        items = []
    items.append(x)
    return items

foo(1)  #return [1]
foo(2)  #return [2]
foo(3)  #return [3]

[] - это объект, поэтому None (первый является изменяемым, в то время как последний является неизменным, но изменчивость не имеет ничего что касается вопроса). Никто не находится где-то в пространстве, но мы знаем, что он есть, и там есть только одна копия «Нет». Таким образом, каждый раз, когда вызывается foo, элементы оцениваются (в отличие от некоторого ответа, который оценивается только один раз) равны None, чтобы быть ясным, ссылка (или адрес) None. Затем в foo элемент изменяется на [], т. Е. Указывает на другой объект, который имеет другой адрес.

====== № 3 =======

def foo(x, items=[]):
    items.append(x)
    return items

foo(1)    # returns [1]
foo(2,[]) # returns [2]
foo(3)    # returns [1,3]

Вызов элемента foo (1) указывает на объект списка [] с адрес, скажем, 11111111. содержимое списка будет изменено на 1 в функции foo в дальнейшем, но адрес не изменится, еще 11111111. Тогда foo (2, []) является приходит. Хотя [] в foo (2, []) имеет тот же контент, что и параметр по умолчанию [] при вызове foo (1), их адрес отличается! Поскольку мы предоставляем параметр явно, items должен принять адрес этого нового [], скажем 2222222, и вернуть его после внесения некоторых изменений. Выполняется foo (3). поскольку предоставляется только x, элементы должны снова принимать значение по умолчанию. Что такое значение по умолчанию? Он задается при определении функции foo: объект списка, расположенный в 11111111. Таким образом, элементы оцениваются как адрес 11111111, имеющий элемент 1. Список, расположенный в 2222222, также содержит один элемент 2, но он не указывается элементами any Больше. Следовательно, добавление 3 сделает items [1,3].

Из приведенных выше объяснений видно, что веб-страница effbot , рекомендованная в принятом ответе, не дала соответствующего ответа на этот вопрос. Более того, я думаю, что точка на веб-странице effbot неверна. Я думаю, что код UI.Button верен:

for i in range(10):
    def callback():
        print "clicked button", i
    UI.Button("button %s" % i, callback)

Каждая кнопка может содержать определенную функцию обратного вызова, которая будет отображать различное значение i. Я могу привести пример, чтобы показать это:

x=[]
for i in range(10):
    def callback():
        print(i)
    x.append(callback) 

Если мы выполним x[7](), мы получим 7, как ожидалось, и x[9]() даст 9, другое значение i.

11
задан Nawaz 17 September 2011 в 19:33
поделиться

6 ответов

Disposed не означает, что он ушел. Disposed означает, что был удален любой неуправляемый ресурс (например, файл, соединение любого типа ...). Хотя это обычно означает, что объект не предоставляет каких-либо полезных функций, могут быть методы, которые не зависят от этого неуправляемого ресурса и все еще работают как обычно.

Механизм удаления существует как .net ( и наследовать, C # .net) - это сборка мусора, то есть вы не отвечаете за управление памятью. Однако сборщик мусора не может решить, закончил ли неуправляемый ресурс использовать, поэтому вам нужно сделать это самостоятельно.

Если вы хотите, чтобы методы генерировали исключение после того, как объект был отключен, ll нужно логическое для захвата статуса dispose, и как только объект будет удален, вы выбросите исключение:

public class A : IDisposable
{
   int i = 100;
   bool disposed = false;
   public void Dispose()
   {
      disposed = true;
      Console.WriteLine("Dispose() called");
   }
   public void f()
   {
      if(disposed)
        throw new ObjectDisposedException();

      Console.WriteLine("{0}", i); i  *= 2;
   }
}
11
ответ дан Femaref 22 August 2018 в 00:54
поделиться
  • 1
    Disposed should означает, что освобождается любой неуправляемый ресурс. Но это не обязательно, если класс плохо реализован. – svick 18 September 2011 в 03:17
  • 2
    Очевидно. Но так обстоит дело с любым критическим поведением, я принял идеальный случай. – Femaref 18 September 2011 в 03:23
  • 3
    Но согласно Dispose pattern dispose означает, что управляемые и неуправляемые ресурсы освобождаются при вызове из клиента извне. В этом случае я не ожидаю, что какой-либо метод не будет работать. правильно? – YakRangi 23 October 2017 в 13:42

Исключение не выбрасывается, потому что вы не разработали методы для броска ObjectDisposedException после того, как был вызван Dispose.

Clr не умеет автоматически знать, что он должен бросить ObjectDisposedException после Dispose называется. Вы несете ответственность за выброс исключения, если Dispose выпустил все ресурсы, необходимые для успешного выполнения ваших методов.

6
ответ дан Giorgi 22 August 2018 в 00:54
поделиться

Обычная реализация Dispose () только вызывает Dispose () для любых объектов, которые она хранит в своих полях, которые являются одноразовыми. Это, в свою очередь, освобождает неуправляемые ресурсы. Если вы реализуете IDisposable и на самом деле ничего не делаете, как в своем фрагменте, то состояние объекта вообще не изменяется. Ничто не может пойти не так. Не смешивать удаление с завершением.

3
ответ дан Hans Passant 22 August 2018 в 00:54
поделиться

Устранение в C # не совпадает с деструктором в C ++. Устранение используется для освобождения управляемых (или неуправляемых) ресурсов, пока объект остается в силе.

Исключения выбрасываются в зависимости от реализации класса. Если f() не требует использования ваших уже размещенных объектов, тогда не обязательно нужно исключать исключение.

2
ответ дан Marlon 22 August 2018 в 00:54
поделиться

Вызов Dispose() не устанавливает ссылку на объект на null, и ваш пользовательский одноразовый класс не содержит никакой логики для исключения исключения, если его функции доступны после того, как Dispose() был вызван так, что он Конечно.

В реальном мире Dispose() освобождает неуправляемые ресурсы, и эти ресурсы будут недоступны после этого, и / или автор класса забрасывает ObjectDisposedException, если вы попытаетесь использовать объект после вызова Dispose(). Обычно логическое значение уровня класса должно быть установлено в true в теле Dispose(), а это значение проверяется в других членах класса до того, как они выполнят какую-либо работу, за исключением того, что значение bool истинно.

2
ответ дан Stephen Kennedy 22 August 2018 в 00:54
поделиться

Цель IDisposable - разрешить объекту фиксировать состояние любых внешних объектов, которые в своей выгоде были помещены в состояние, которое является менее идеальным для других целей. Например, объект Io.Ports.SerialPort, возможно, изменил состояние последовательного порта с «доступным для любого приложения, которое хочет, чтобы оно было« доступно только одному объекту Io.Ports.SerialPort »; основная цель SerialPort.Dispose - восстановить состояние последовательного порта «доступно для любого приложения».

Конечно, как только объект, реализующий IDisposable, сбросил объекты, которые поддерживали определенное состояние для его выгоды, он больше не будет иметь преимущества от состояния, поддерживаемого этими субъектами. Например, если состояние последовательного порта установлено в «доступно для любого приложения», потоки данных, с которыми он был связан, больше не могут использоваться для отправки и приема данных. Если бы объект мог нормально функционировать, если внешние сущности не были помещены в особое состояние для своей выгоды, не было бы причин оставлять внешние объекты в специальном состоянии в первую очередь.

Как правило, после IDisposable.Dispose был вызван на объект, нельзя ожидать, что объект способен много сделать. Попытка использовать большинство методов для такого объекта указывает на ошибку; если метод не может разумно ожидать, что он будет работать, правильный способ указать это через ObjectDisposedException.

Microsoft предполагает, что почти все методы объекта, который реализует IDisposable, должны бросать ObjectDisposedException, если они используются на объект, который был удален. Я бы предположил, что такой совет слишком широк. Часто бывает полезно использовать устройства для выявления методов или свойств, чтобы узнать, что произошло во время жизни объекта. Хотя можно было бы дать классу связи метод Close, а также метод Dispose, и позволить только запрашивать такие вещи, как NumberOfPacketsExchanged, после закрытия, но не после Dispose, но это кажется чрезмерно сложным. Чтение свойств, связанных с вещами, которые произошли до того, как объект был удален, выглядит вполне разумным.

2
ответ дан supercat 22 August 2018 в 00:54
поделиться
Другие вопросы по тегам:

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