2016-07-22 5 views
1

У меня есть огромный массив меток, которые я делаю уникальный через:Добавив объект набора является `NoneType` питона 2,7

unique_train_labels = set(train_property_labels) 

, который печатает, как set([u'A', u'B', u'C']). Я хочу, чтобы создать новый набор уникальных этикеток с новым лейблом под названием «no_region», и я использую:

unique_train_labels_threshold = unique_train_labels.add('no_region') 

Однако это распечатывает быть None.

Моя конечная цель состоит в том, чтобы использовать эти уникальные этикетки, чтобы впоследствии сгенерировать массив случайных категориальных меток через:

rng = np.random.RandomState(101) 

    categorical_random = rng.choice(list(unique_train_labels), len(finalTestSentences)) 
    categorical_random_threshold = rng.choice(list(unique_train_labels_threshold), len(finalTestSentences)) 

Из docs говорится, что set.add() должен создать новый набор, который, кажется, не быть случай (следовательно, не могу назвать позже list(unique_train_labels_threshold))

+0

Где в документах говорится, что метод add генерирует новый набор? Я только нашел: * s.add (x) \t \t добавить элемент x, чтобы установить s * – cdarke

+0

, вы должны сделать это за 2 раза. сначала вы храните 'unique_train_labels' в' unique_train_labels_threshold', затем вызываете 'add()' on 'unique_train_labels_threshold',' a_set.add (stuff) 'always' return none' – pwnsauce

+0

@cdarke да, вот что я имел в виду, он говорит, что добавляет элемент для набора, который для меня, кажется, подразумевает, что набор все равно должен быть там. –

ответ

3

Как уже упоминалось в ответ Моисея, метод set.add мутирует оригинальный набор, он не создает новый набор. В Python стандартно для методов, которые выполняют мутацию на месте, чтобы вернуть None; методы всех встроенных изменяемых типов делают это, и соглашение обычно наблюдается в сторонних библиотеках.

Альтернативой использованию метода .copy является использование метода .union, который возвращает новый набор, являющийся объединением исходного набора и набора, предоставленного в качестве аргумента. Для наборов оператор или вызывает метод .union.

a = {1, 2, 3} 
b = a.union({5}) 
c = a | {4} 
print(a, b, c) 

выход

{1, 2, 3} {1, 2, 3, 5} {1, 2, 3, 4} 

Метод .union (как и другие методы набора, которые могут быть вызваны с помощью синтаксиса оператора) имеют небольшое преимущество над синтаксисом оператора: вы можете передать его любого Iterable за его аргумент; версия оператора требует, чтобы вы явно преобразовали аргумент в набор (или frozenset).

a = {1, 2, 3} 
b = a.union([5, 6]) 
c = a | set([7, 8]) 
print(a, b, c) 

выход

{1, 2, 3} {1, 2, 3, 5, 6} {1, 2, 3, 7, 8} 

Используя явный .union метод является немного более эффективным здесь, потому что он обходит преобразования ARG к набору: Внутри метода только перебирает содержимое арг, добавив их в новый набор, поэтому не имеет значения, является ли arg набором, списком, кортежем, строкой или dict.

Из официального Python set docs

Примечание, не-оператор версии объединения(), пересечения(), разность() и symmetric_difference(), issubset(), и issuperset() методы будут принимать любые итерации в качестве аргумента. Напротив, их операторы, основанные на операторах, требуют, чтобы их аргументы были наборами. Этот номер исключает ошибки, связанные с конструкциями типа set ('abc') & 'cbs' в пользу более читаемого набора ('abc'). Intersection ('cbs').

+0

Спасибо @PM 2Ring, это сработало! –

4

набор add метод мутирует множество InPlace и возвращает None.

Вы должны сделать:

unique_train_labels_threshold = unique_train_labels.copy() 
unique_train_labels_threshold.add('no_region') 

Использование copy обеспечивает мутации в новом наборе не распространяются на старой.

+0

Извините, это не работает - оно все равно печатает на 'None'. –

+0

Вы как-то изменили исходный набор на «Нет». Создайте этот первый набор –

+0

@DhruvGhulati, это должно сработать. Я не уверен, что 'copy()' необходимо (я пробовал без python3, и он работал отлично) – pwnsauce

0

Я не могу найти в документации нигде, если бы он сказал, что add создает новый набор.
Вам необходимо скопировать оригинал, а затем добавить новую копию.

import copy 

unique_train_labels_threshold = copy.deepcopy(unique_train_labels) 
unique_train_labels_threshold.add('no_region') 
+0

Извините, это не работает - оно все равно выводится на' None'. –

+0

Использование 'deepcopy' на множестве элементов является излишним. Метод 'set.copy' всегда достаточен, так как множество элементов должно быть абсолютно неизменным. Вы даже не можете сделать кортеж списков заданного элемента. –

+0

@ PM2Ring: причина, по которой я использую это, потому что в документе конкретно говорится, что метод 'copy' выполняет мелкую копию. – cdarke

Смежные вопросы