Как и во всех хороших примерах, вы упростили то, что вы на самом деле пытаетесь сделать. Это хорошо, но стоит отметить, что python имеет гибкость , когда дело доходит до переменных класса и экземпляра. То же самое можно сказать о методах. Для хорошего списка возможностей я рекомендую прочитать введение новых классов в стиле Michael Fötsch , особенно разделы с 2 по 6.
Одна вещь, которая требует много работы, чтобы помнить, когда начало работы заключается в том, что python не является java. Больше, чем просто клише. В java компилируется весь класс, что делает разрешение пространства имен реальным простым: любые переменные, объявленные вне метода (в любом месте), являются переменными экземпляра (или, если статические, классные) и неявно доступны в методах.
С помощью python главное правило состоит в том, что для переменных есть три пространства имен:
{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!), Или идея ссылаться на имя вашего класса внутри самого класса кажется вам неправильной, проверьте интро я связал.
он не удаляется из WeakSet. Почему это?
blockquote>Скорее всего потому, что сборщик мусора еще не запущен. Тем не менее, вы говорите, что используете Traceur, поэтому просто может быть, что они не поддерживаются должным образом. Интересно, как
console
может показать содержимоеWeakSet
в любом случае.В чем смысл добавлять объекты непосредственно к WeakSets?
blockquote>Нет смысла добавлять литералы объектов к
WeakSet
s.Что такое практическое использование WeakSet, если мы даже не можем его прокручивать или не получаем текущий размер?
< / blockquote>Все, что вы можете получить, это один бит информации: Является ли объект (или вообще, значение), содержащийся в наборе?
Это может быть полезно в ситуациях, когда вы хотите «пометить», объекты, фактически не изменяя их (устанавливая на них свойство). Многие алгоритмы содержат какое-то «если
x
уже было замечено» условие (возможно, обнаружение циклаJSON.stringify
может быть хорошим примером), а когда вы работаете с предоставленными пользователем значениями, используйтеSet
/WeakSet
было бы целесообразно. ПреимуществоWeakSet
здесь в том, что его содержимое может быть собрано в мусор, пока ваш алгоритм все еще работает, поэтому он помогает сократить потребление памяти (или даже предотвращает утечки), когда вы имеете дело с большим количеством данных, которые лениво (возможно даже асинхронно).
Это очень трудный вопрос. Чтобы быть абсолютно честным, я понятия не имел в контексте 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
)
makeRequest
, так как запросы обычно считаются разовыми.
– ssube
2 June 2015 в 16:16
makeRequest
могут быть сделаны? Что делать, если экземпляры ApiRequest
передаются, но иногда вообще не используются (0 вызовов)? Причина, по которой он должен быть слабым, заключается в том, чтобы не связывать время жизни запросов с множеством.
– Benjamin Gruenbaum
2 June 2015 в 16:17
if(static_symbol !== arg1) throw new Error("Invalid access");
. stackoverflow.com/questions/29413222/… Использование слабого для этого в значительной степени является взломом.
– Pacerier
18 September 2017 в 21:28
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.
};
По определению 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.
processedBag.has(nextObject)
всегда будет возвращать true после того, как вы вставили объект, потому что, ссылаясь на него, вы прекращаете сбор GC. Другими словами, ваша мощь также использовала обычный набор , если вам не нужны возможности автоопределения слабого, когда var выходит за рамки.
– Pacerier
18 September 2017 в 16:09
nextObject = getNext();
не даст другого объекта, который может быть не в processedBag
?
– Paul Stelian
7 July 2018 в 01:02
.size
недоступны в WeakSets, потому что они не будут надежными? Сборщик мусора работает всякий раз, когда захочет, чтобы информация не использовалась. Но.has()
- другая история, потому что, если у нас есть какая-либо ссылка, чтобы передать ее методу.has()
, сборщик мусора наверняка не очистил его. Является ли мое понимание разумным? :) – Robo Robok 31 May 2015 в 10:24WeakSet
, но они могут привести к недетерминированным алгоритмам (в зависимости от поведения GC), если они используются неверно, и поэтому комитет ES решил не делать содержимое доступно. – Bergi 31 May 2015 в 10:28