можно ли приковать вызов метода к встроенному set ()? (и почему бы нет?) - PullRequest
3 голосов
/ 15 апреля 2009

Если я попытаюсь:

mi_list = ['three', 'small', 'words']
mi_set = set(mi_list)
mi_set.remove('small')
print mi_set  

Я получаю:

set(['three', 'words'])  

что я и ожидаю. Тогда как если я попытаюсь:

mi_list = ['three', 'small', 'words']
mi_set = set(mi_list).remove('small')
print mi_set

Я получаю:

None

Почему?

Я подозреваю, что есть подсказка, что если я пытаюсь удалить элемент, которого нет - например, "большой" - появляется сообщение об ошибке:

KeyError: 'big'

Ответы [ 6 ]

20 голосов
/ 15 апреля 2009

set.remove ничего не возвращает (нет).

Ваш код назначает возвращаемое значение set.remove переменной mi_set. Следовательно, mi_set - это None.

8 голосов
/ 16 апреля 2009

В Python существует общее соглашение, согласно которому методы, вызывающие побочные эффекты , возвращают None . Примеры включают list.sort, list.append, set.add, set.remove, dict.update и т. Д.

Это по сути, чтобы помочь вам избежать ошибок. Скажем, у вас был набор под названием mi_set. Если бы вы могли написать:

mi_set2 = mi_set.remove('small')

тогда читатель может подумать: «mi_set2 отличается от mi_set». Но это было бы не так! А путаница может привести к незаметным ошибкам, вызванным ошибочным совместным использованием структур данных. Поэтому, возвращая None, python заставляет вас помнить, что методы, подобные тем, которые я перечислил выше, изменяют объекты, а не создают новые.

См. Также длинное обсуждение здесь . Хотя обратите внимание, что такие методы, как sorted() и reversed(), были добавлены с этого потока.

[обратите внимание, что list.pop является исключением из этого правила по историческим причинам - он позволяет вам использовать список как стек. И даже тогда он возвращает удаленный объект, а не список.]

1 голос
/ 15 апреля 2009

Почему возвращается None? Потому что .remove, .add и т. Д. Возвращают None :) Вот и все. Они не поддерживают цепочку.

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

class chain_set(set):
   def chain_add(self, x):
      newself = self.copy()
      newself.add(x)
      return newself

cs = chain_set([1,2,3,4])
cs.chain_add(5)
# chain_set([1, 2, 3, 4, 5])
cs.chain_add(7)
# chain_set([1, 2, 3, 4, 7])
cs.chain_add(7).chain_add(8)
# chain_set([1, 2, 3, 4, 7, 8])

Проблема в том, ожидаете ли вы, что cs изменится?

Вы всегда хотите изменить исходный набор (может создать некоторые трудно обнаруживаемые ошибки) или хотите копировать набор каждый раз (может быть медленнее с большими наборами). Если вы знаете, какое поведение вам нужно, и помните об этом, просто продолжайте реализацию собственного набора.

1 голос
/ 15 апреля 2009

В вашем случае можно было бы использовать член разница :

>>> a = set(["a", "b", "c"])
>>> a = a.difference(["a"])
>>> print a
set(['c', 'b'])

Разница в том, что remove действует на текущий набор (функции-члены объекта библиотеки Python, которые изменяют экземпляр, обычно возвращают None), тогда как diff создает и возвращает новый набор.

0 голосов
/ 16 апреля 2009

remove изменяет исходный набор, ничего не возвращая (или, скорее, он возвращает None). Этот пример показывает, что происходит с исходным объектом, когда вы вызываете на нем команду remove:

Python 3.0.1 (r301:69561, Feb 13 2009, 20:04:18) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> lst = [1,2,3]
>>> s1 = set(lst)
>>> s1
{1, 2, 3}
>>> s2 = s1.remove(2)  # instead of reassigning s1, I save the result of remove to s2
>>> s1
{1, 3}  # *** 2 is not an element in the original set ***
>>> s2  # s2 is not a set at all!
>>> 

Чтобы ответить на другую часть вашего вопроса, исключение указывает, что команда remove пыталась удалить аргумент из набора, но не смогла, поскольку аргумента нет в наборе. И наоборот, delete возвращает None, что указывает на успех.

0 голосов
/ 15 апреля 2009

Вы уверены, что функция remove возвращает значение?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...