WeakSet: сбор мусора не работает? [Дубликат]

Как и во всех хороших примерах, вы упростили то, что вы на самом деле пытаетесь сделать. Это хорошо, но стоит отметить, что python имеет гибкость , когда дело доходит до переменных класса и экземпляра. То же самое можно сказать о методах. Для хорошего списка возможностей я рекомендую прочитать введение новых классов в стиле Michael Fötsch , особенно разделы с 2 по 6.

Одна вещь, которая требует много работы, чтобы помнить, когда начало работы заключается в том, что python не является java. Больше, чем просто клише. В java компилируется весь класс, что делает разрешение пространства имен реальным простым: любые переменные, объявленные вне метода (в любом месте), являются переменными экземпляра (или, если статические, классные) и неявно доступны в методах.

С помощью python главное правило состоит в том, что для переменных есть три пространства имен:

  1. Функция / метод
  2. Текущий модуль
  3. g4]
  4. Встроенные

{begin pedagogy}

Есть исключения для этого. Главное, что происходит со мной, заключается в том, что при загрузке определения класса определение класса является его собственным неявным пространством имен. Но это продолжается только до тех пор, пока модуль загружается и полностью исключается, когда внутри метода. Таким образом:

>>> class A(object):
        foo = 'foo'
        bar = foo


>>> A.foo
'foo'
>>> A.bar
'foo'

, но:

>>> class B(object):
        foo = 'foo'
        def get_foo():
            return foo
        bar = get_foo()



Traceback (most recent call last):
  File "", line 1, in 
    class B(object):
  File "", line 5, in B
    bar = get_foo()
  File "", line 4, in get_foo
    return foo
NameError: global name 'foo' is not defined

{end pedagogy}

В конце концов, нужно помнить, что вы / g2] имеют доступ к любой из переменных, к которым вы хотите получить доступ, но, вероятно, неявно. Если ваши цели просты и понятны, то для Foo.bar или self.bar, вероятно, будет достаточно. Если ваш пример становится более сложным или вы хотите делать причудливые вещи, такие как наследование (вы можете наследовать методы static / class!), Или идея ссылаться на имя вашего класса внутри самого класса кажется вам неправильной, проверьте интро я связал.

38
задан Robo Robok 2 June 2015 в 16:57
поделиться

4 ответа

он не удаляется из WeakSet. Почему это?

Скорее всего потому, что сборщик мусора еще не запущен. Тем не менее, вы говорите, что используете Traceur, поэтому просто может быть, что они не поддерживаются должным образом. Интересно, как console может показать содержимое WeakSet в любом случае.

В чем смысл добавлять объекты непосредственно к WeakSets?

Нет смысла добавлять литералы объектов к WeakSet s.

Что такое практическое использование WeakSet, если мы даже не можем его прокручивать или не получаем текущий размер?

< / blockquote>

Все, что вы можете получить, это один бит информации: Является ли объект (или вообще, значение), содержащийся в наборе?

Это может быть полезно в ситуациях, когда вы хотите «пометить», объекты, фактически не изменяя их (устанавливая на них свойство). Многие алгоритмы содержат какое-то «если x уже было замечено» условие (возможно, обнаружение цикла JSON.stringify может быть хорошим примером), а когда вы работаете с предоставленными пользователем значениями, используйте Set / WeakSet было бы целесообразно. Преимущество WeakSet здесь в том, что его содержимое может быть собрано в мусор, пока ваш алгоритм все еще работает, поэтому он помогает сократить потребление памяти (или даже предотвращает утечки), когда вы имеете дело с большим количеством данных, которые лениво (возможно даже асинхронно).

38
ответ дан Bergi 23 August 2018 в 00:15
поделиться
  • 1
    Благодарим вас за использование слова «маркировка». - Теперь я все понимаю. Итак, итерация и .size недоступны в WeakSets, потому что они не будут надежными? Сборщик мусора работает всякий раз, когда захочет, чтобы информация не использовалась. Но .has() - другая история, потому что, если у нас есть какая-либо ссылка, чтобы передать ее методу .has(), сборщик мусора наверняка не очистил его. Является ли мое понимание разумным? :) – Robo Robok 31 May 2015 в 10:24
  • 2
    @RoboRobok: Именно то, что :-) Можно было бы сделать реализационные реализации WeakSet, но они могут привести к недетерминированным алгоритмам (в зависимости от поведения GC), если они используются неверно, и поэтому комитет ES решил не делать содержимое доступно. – Bergi 31 May 2015 в 10:28
  • 3
    @RoboRobok Я думаю, что другой ответ очень хорошо показывает основное использование WeakSet. Я не думаю, что он будет часто использоваться в коде приложения, но очень часто в таких библиотеках, как jQuery и Angular. Вероятно, есть неэффективность в отношении того, как такие вещи обрабатываются в SPA (одностраничное приложение) с интенсивной загрузкой данных AJAX, когда управление памятью становится сложным в течение длительных периодов времени. Когда у вас есть стандартная веб-страница с ориентацией на страницы, все равно выбрасывается, поэтому управление памятью не является проблемой. – pid 31 May 2015 в 10:29
  • 4
    @pid Спасибо за ваше объяснение. Еще одна вещь: если добавление чего-либо к WeakSet напрямую не имеет смысла, может ли это (теоретически) вызвать ошибку, если мы попытаемся это сделать? Или, возможно, в JavaScript невозможно определить, передается ли что-либо переменной или нет? – Robo Robok 31 May 2015 в 11:18
  • 5
    @RoboRobok: Это больше для linter или зависящей от реализации функции (опираясь на материал внутреннего представления). В простом JavaScript все объекты являются ссылочными значениями, и когда объект передается функции, нет никакой заметной разницы между объектом, который строится «на лету» из литерала и объекта, который хранится в переменной. – Bergi 31 May 2015 в 12:55

Это очень трудный вопрос. Чтобы быть абсолютно честным, я понятия не имел в контексте JavaScript , поэтому я спросил в esdiscuss и получил убедительный ответ от Domenic .

WeakSets полезны для аргументов security и validation . Если вы хотите изолировать фрагмент JavaScript. Они позволяют вам помечать объект, чтобы указать, что он принадлежит к определенному набору объектов.

Предположим, у меня есть класс ApiRequest:

class ApiRequest {
  constructor() {
    // bring object to a consistent state, use platform code you have no cirect access to
  }

  makeRequest() {
    // do work 
  }
}

Теперь я написание платформы JavaScript - моя платформа позволяет запускать JavaScript для совершения звонков - чтобы сделать эти вызовы вам нужно ApiRequest - я хочу, чтобы вы сделали ApiRequest с объектами, которые я вам даю, чтобы вы не могли обойти любые

Однако на данный момент ничто не мешает вам:

ApiRequest.prototype.makeRequest.call(null, args); // make request as function
Object.create(ApiRequest.prototype).makeRequest(); // no initialization
function Foo(){}; Foo.prototype = ApiRequest.prototype; new Foo().makeRequest(); // no super

И так далее, обратите внимание, что вы не можете сохранить обычный список или массив объектов ApiRequest, поскольку это предотвратит их сбор мусора. Помимо закрытия, все может быть достигнуто с помощью общедоступных методов, таких как Object.getOwnPropertyNames или Object.getOwnSymbols. Итак, вы подходите ко мне и делаете:

const requests = new WeakSet();
class ApiRequest {
  constructor() {
    requests.add(this);
  }

  makeRequest() {
    if(!request.has(this)) throw new Error("Invalid access");
    // do work
  }
}

Теперь, независимо от того, что я делаю, я должен содержать действительный объект ApiRequest для вызова метода makeRequest. Это невозможно без WeakMap / WeakSet.

Итак, короче говоря - WeakMaps полезны для написания платформ в JavaScirpt. Обычно этот вид проверки выполняется на стороне C ++, но добавление этих функций позволит перемещать и создавать вещи в JavaScript.

(Конечно, все, что WeakSet делает WeakMap, который отображает значения в true, но это верно для любой конструкции map / set)

(Как говорит Берги, никогда не бывает причин добавлять литерал объекта непосредственно к WeakMap или WeakSet )

24
ответ дан Community 23 August 2018 в 00:15
поделиться
  • 1
    Разве вы не можете сделать большую часть этого с помощью сильных наборов? Вам нужно будет удалить их в определенный момент или запросить утечку, но это легко можно сделать в методе makeRequest, так как запросы обычно считаются разовыми. – ssube 2 June 2015 в 16:16
  • 2
    @ssube, если несколько вызовов makeRequest могут быть сделаны? Что делать, если экземпляры ApiRequest передаются, но иногда вообще не используются (0 вызовов)? Причина, по которой он должен быть слабым, заключается в том, чтобы не связывать время жизни запросов с множеством. – Benjamin Gruenbaum 2 June 2015 в 16:17
  • 3
    @BenjaminGruenbaum, 1) Если полезность ограничена простотой написания таких платформ, нужно сказать, что ее никогда не добавляли на основной язык вообще. 2) . Такие платформы можно записать с помощью if(static_symbol !== arg1) throw new Error("Invalid access");. stackoverflow.com/questions/29413222/… Использование слабого для этого в значительной степени является взломом. – Pacerier 18 September 2017 в 21:28
  • 4
    @Pacerier 2) нет, он не может, и это, конечно, не хак - на случай, если вы не знаете людей, чей ответ, который я получил в esdiscuss, - это люди, добавляющие материал на язык: D – Benjamin Gruenbaum 17 April 2018 в 18:16

WeakSet - это упрощение WeakMap, где ваша ценность всегда будет логической. Это позволяет вам помечать объекты JavaScript, чтобы только что-то делать с ними один раз или поддерживать свое состояние в отношении определенного процесса. Теоретически, поскольку он не должен содержать значение, он должен использовать немного меньше памяти и выполнять несколько быстрее, чем WeakMap.

var [touch, untouch] = (() => {
    var seen = new WeakSet();
    return [
        value => seen.has(value)) || (seen.add(value), !1),
        value => !seen.has(value) || (seen.delete(value), !1)
    ];
})();

function convert(object) {
    if(touch(object)) return;
    extend(object, yunoprototype); // Made up.
};

function unconvert(object) {
    if(untouch(object)) return;
    del_props(object, Object.keys(yunoprototype)); // Never do this IRL.
};
1
ответ дан jgmjgm 23 August 2018 в 00:15
поделиться
  • 1
    Ваш примерный код не объясняет, как используется слабый набор. – Pacerier 18 September 2017 в 16:15
  • 2
    Я, должно быть, спешил. Описание более важно. Код - это стерха / прототип для изменения объекта один раз и только один раз (например, его расширение, полиморфизм времени выполнения). – jgmjgm 18 September 2017 в 17:36

По определению WeakSet имеет только три ключевые функции

  • Слабо связать объект с множеством
  • Удалить ссылку на объект из набора
  • Проверьте, был ли объект уже привязан к набору

Звучит более знакомо?

В некоторых приложениях разработчикам, возможно, потребуется реализовать быстрый способ для повторения серии данных, которая загрязнена партиями и множеством избыточности , но вы хотите выбрать только те, которые не были обработаны до (уникальные) . WeakSet может вам помочь. Пример ниже:

var processedBag = new WeakSet();
var nextObject = getNext();
while (nextObject !== null){
    // Check if already processed this similar object?
    if (!processedBag.has(nextObject)){
        // If not, process it and memorize 
        process(nextObject);
        processedBag.add(nextObject);
    }
    nextObject = getNext();
}

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

8
ответ дан Tao P. R. 23 August 2018 в 00:15
поделиться
  • 1
    Обратите внимание, что processedBag.has(nextObject) всегда будет возвращать true после того, как вы вставили объект, потому что, ссылаясь на него, вы прекращаете сбор GC. Другими словами, ваша мощь также использовала обычный набор , если вам не нужны возможности автоопределения слабого, когда var выходит за рамки. – Pacerier 18 September 2017 в 16:09
  • 2
    Разве строка nextObject = getNext(); не даст другого объекта, который может быть не в processedBag? – Paul Stelian 7 July 2018 в 01:02
Другие вопросы по тегам:

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