Повернення логічного значення, якщо значення порожнє


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, оскільки мені не потрібні значення, я просто хочу знати, чи вони перетинаються.


4
порожній набір вважається логічним неправдивим еквівалентом, якщо ви його кидаєте так:bool(set([]))
woozyking

3
до речі, серйозно добре відпрацьоване питання, яке примітно.
Йонас Шефер,

@JonasWielicki Дякую! Цінуйте відповідь - знав, що це щось подібне.
CB

Це питання перетвориться на 5 років, і ніхто не пропонував його використовувати isdisjoint. Я абсолютно вражений.
Адіріо

Відповіді:


67
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, але я не маю впливу на те, що прийнято ОП ...)
Йонас Шефер,

108

не такий пітонічний, як інші відповіді, але математика:

return len(c) == 0

Як зауважували деякі коментарі щодо впливу, який len(set)може мати на складність. Це O (1), як показано у вихідному коді, оскільки воно покладається на змінну, яка відстежує використання набору.

static Py_ssize_t
set_len(PyObject *so)
{
    return ((PySetObject *)so)->used;
}

9
Я думаю, що це насправді краще. Це стає зрозумілішим, що ви маєте намір.
arshajii

4
Боюся, це доведеться обчислювати, len(c)навіть якщо cвоно дуже велике, що непотрібно для перевірки на порожнечу.
Мікеле Де Паскаліс,

1
@Glaedr Я вважаю, що cpython len для загальновживаних структур даних (тобто списку, набору) є O (1) (тобто вони зберігають змінну в структурі даних, що представляє довжину)
CB

2
^ +1 @CB я провів кілька тестів на len (c), і це, безумовно, якась змінна, що представляє len, оскільки була незначна різниця у виконанні, коли встановлений розмір міняв різкі порядки величини.
dster77

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 посилаються на один і той же об’єкт. Ось що робить оператор "є". У python None - це спеціальне нульове значення, яке зазвичай означає, що у вас немає доступного значення. Сорта, як нуль в 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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.