Возвращение логического значения, если установлено пустое

97

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

Я беру пересечение двух наборов и хочу вернуться Trueили в Falseзависимости от того, пуст ли результирующий набор.

def myfunc(a,b):
    c = a.intersection(b)
    #...return boolean here

Моей первоначальной мыслью было сделать

return c is not None

Однако в моем интерпретаторе я легко вижу, что оператор вернет истину, если c = set([])

>>> c = set([])
>>> c is not None
True

Я также пробовал все следующее:

>>> c == None
False
>>> c == False
False
>>> c is None
False

Теперь я прочитал в документации , что я могу использовать только and, orи notс пустыми множествами вывести логическое значение. Пока единственное, что я могу придумать, это вернуть не c

>>> not not c
False
>>> not c
True

У меня есть чувство, что есть гораздо более питонический способ сделать это, но я изо всех сил пытаюсь его найти. Я не хочу возвращать фактический набор в оператор if, потому что мне не нужны значения, я просто хочу знать, пересекаются ли они.

CB
источник
4
пустой набор считается логическим эквивалентом False, если вы его bool(set([]))
приведете
3
Кстати, серьезно проработанный вопрос, что примечательно.
Йонас Шефер
@JonasWielicki Спасибо! Оцените ответ - знал, что это что-то в этом роде.
CB
Этому вопросу исполнится 5 лет, и никто не предлагал использовать isdisjoint. Я в полном шоке.
Adirio

Ответы:

70
def myfunc(a,b):
    c = a.intersection(b)
    return bool(c)

bool()сделаю что-то подобное not not, но более идеальное и понятное.

Йонас Шефер
источник
7
Я возражаю, писать, bool(...)когда вы спрашиваете is_empty, непонятно. Я не выражаю намерения.
tamas.kenez
2
@ tamas.kenez Однако согласитесь, что это понятнее, чем not not;). (FTR: я уже проголосовал за ответ @gefeis, но я не имею влияния на то, что OP принял…)
Йонас Шефер
109

не такой питонический, как другие ответы, а математика:

return len(c) == 0

Как некоторые комментарии задавались вопросом о влиянии, которое len(set)может иметь на сложность. Это O (1), как показано в исходном коде, поскольку он зависит от переменной, которая отслеживает использование набора.

static Py_ssize_t
set_len(PyObject *so)
{
    return ((PySetObject *)so)->used;
}
Gefei
источник
9
Я думаю, что это на самом деле лучше. Это проясняет ваши намерения.
arshajii
4
Боюсь, что это придется вычислить, len(c)даже если cон очень большой, что не нужно для проверки на пустоту.
Мишель Де Паскалис,
1
@Glaedr Я верю, что cpython len для часто используемых структур данных (например, список, набор) имеет значение O (1) (т.е. они хранят переменную в структуре данных, представляющую длину)
CB
2
^ +1 @CB Я провел несколько тестов для len (c), и это определенно некоторая переменная, представляющая len, потому что разница во времени выполнения была незначительной, когда размер набора резко изменился на порядки.
dster77 02
1
@ dster77 я профилировал свой код для обеих версий, и он был значительно быстрее по сравнению с set()(python 3.5.2 в Windows)
mathiasfk
23

Если вы хотите return Trueпустой набор, то, думаю, было бы проще сделать:

return c == set()

т.е. " cравно пустому set".

(Или, наоборот, return c != set()).

На мой взгляд, это более явно (хотя и менее идиоматично), чем полагаться на интерпретацию Python пустого набора как Falseв логическом контексте.

Джонршарп
источник
2
На самом деле, полагаться на интерпретацию Python - очень приемлемая практика. При условии, что его ограничения учитываются.
вулкан
17

Если cэто множество , то вы можете проверить , является ли это пустым, выполнив: return not c.

Если cпусто, то not cбудет True.

В противном случае, если cсодержит какие-либо элементы, not cбудет False.

Симеон Виссер
источник
6

Когда ты говоришь:

c is not None

Фактически вы проверяете, ссылаются ли c и None на один и тот же объект. Это то, что делает оператор "is". В python None - это специальное нулевое значение, которое обычно означает, что у вас нет доступного значения. Сортировка как null в c или java. Поскольку python внутренне присваивает только одно значение None, используя оператор «is», чтобы проверить, работает ли что-то None (думаю, null), это стало популярным стилем. Однако это не связано со значением истинности набора c, это проверка того, что c действительно является набором, а не нулевым значением.

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

c = set()
if c:
   print "it has stuff in it"
else:
   print "it is empty"

Но если вы хотите, чтобы он был преобразован в логическое значение, чтобы сохранить его, вы можете просто сказать:

c = set()
c_has_stuff_in_it = bool(c)
Эндрю Аллер
источник
1
"""
This function check if set is empty or not.
>>> c = set([])
>>> set_is_empty(c)
True

:param some_set: set to check if he empty or not.
:return True if empty, False otherwise.
"""
def set_is_empty(some_set):
    return some_set == set()
штут штузим
источник
0

Не так чисто, как bool (c), но это был повод использовать тройной.

def myfunc(a,b):
    return True if a.intersection(b) else False

Также, используя ту же логику, нет необходимости назначать c, если вы не используете его для чего-то другого.

def myfunc(a,b):
    return bool(a.intersection(b))

Наконец, я предполагаю, что вам нужно значение True / False, потому что вы собираетесь выполнить с ним какой-то логический тест. Я бы рекомендовал пропустить накладные расходы на вызов и определение функции, просто протестировав там, где вам это нужно.

Вместо того:

if (myfunc(a,b)):
    # Do something

Может быть, это:

if a.intersection(b):
    # Do something
Амос Бейкер
источник