Zwracanie wartości logicznej, jeśli zestaw jest pusty

99

Staram się znaleźć bardziej czysty sposób zwracania wartości logicznej, jeśli mój zestaw jest pusty na końcu mojej funkcji

Biorę przecięcie dwóch zestawów i chcę zwrócić Truelub Falsena podstawie tego, czy wynikowy zestaw jest pusty.

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

Moja pierwsza myśl była taka

return c is not None

Jednak w moim tłumaczu z łatwością widzę, że stwierdzenie zwróci prawdę, jeśli c = set([])

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

Wypróbowałem również wszystkie z poniższych:

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

Teraz już odczytać z dokumentacji, że można używać tylko and, ori notze zbiór pusty wydedukować wartość logiczną. Jak dotąd jedyne, co mogę wymyślić, to powrót nie c

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

Mam wrażenie, że istnieje znacznie bardziej pytoniczny sposób, aby to zrobić, ponieważ staram się go znaleźć. Nie chcę zwracać rzeczywistego zestawu do instrukcji if, ponieważ nie potrzebuję wartości, chcę tylko wiedzieć, czy się przecinają.

CB
źródło
4
pusty zbiór jest uważany za logiczny Fałszywy odpowiednik, jeśli go rzucisz:bool(set([]))
woozyking
3
tak przy okazji, poważnie dopracowane pytanie, co jest niezwykłe.
Jonas Schäfer
@JonasWielicki Thanks! Doceń odpowiedź - wiedziałem, że to coś podobnego.
CB
To pytanie skończy 5 lat i nikt nie sugerował używania isdisjoint. Jestem całkowicie w szoku.
Adirio,

Odpowiedzi:

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

bool()zrobi coś podobnego not not, ale bardziej ideomatycznego i wyraźnego.

Jonas Schäfer
źródło
9
Sprzeciwiam się, pisanie, bool(...)kiedy pytasz, is_emptyjest niejasne. Nie wyrażam zamiaru.
tamas.kenez
2
@ tamas.kenez Trzeba jednak przyznać, że jest to wyraźniejsze niż not not;). (FTR: już przegłosowałem odpowiedź @gefeis, ale nie mam wpływu na to, co OP zaakceptował…)
Jonas Schäfer
113

nie tak pytoniczne jak inne odpowiedzi, ale matematyka:

return len(c) == 0

Jak niektórzy komentatorzy zastanawiali się, jaki wpływ len(set)może mieć na złożoność. Jest to O (1), jak pokazano w kodzie źródłowym, ponieważ opiera się na zmiennej, która śledzi użycie zestawu.

static Py_ssize_t
set_len(PyObject *so)
{
    return ((PySetObject *)so)->used;
}
gefei
źródło
10
Myślę, że tak jest lepiej. To sprawia, że ​​jaśniejsze jest twoje zamiary.
arshajii
4
Obawiam się, że będzie to musiało zostać obliczone, len(c)nawet jeśli cjest bardzo duże, co jest niepotrzebne, aby sprawdzić, czy nie ma pustki.
Michele De Pascalis,
1
@Glaedr Wierzę w cpython len dla powszechnie używanych struktur danych (tj. Lista, zestaw) to O (1) (tj. Przechowują zmienną na strukturze danych reprezentującej długość)
CB
2
^ +1 @CB Przeprowadziłem kilka testów na len (c) i na pewno jest to pewna zmienna reprezentująca len, ponieważ wystąpiła pomijalna różnica w czasie wykonywania, gdy ustawiony rozmiar zmienił się dramatycznie o rząd wielkości.
dster77
1
@ dster77 sprofilowałem mój kod z obiema wersjami i był znacznie szybszy w porównaniu z set()(python 3.5.2 w windows)
mathiasfk
27

Jeśli chcesz return Truemieć pusty zestaw, myślę, że byłoby to bardziej przejrzyste:

return c == set()

tj. „ crówna się pustemu set”.

(Lub na odwrót return c != set()).

Moim zdaniem jest to bardziej wyraźne (choć mniej idiomatyczne) niż poleganie na interpretacji pustego zbioru Falsew Pythonie w kontekście boolowskim.

jonrsharpe
źródło
2
W rzeczywistości poleganie na interpretacji Pythona jest bardzo akceptowalną praktyką. O ile pamiętasz o jego ograniczeniach.
wulkan
18

Jeśli cjest zbiorem następnie można sprawdzić, czy jest ona pusta, wykonując: return not c.

Jeśli cjest pusty, not cbędzie True.

W przeciwnym razie, jeśli czawiera jakieś elementy, not cbędzie False.

Simeon Visser
źródło
7

Kiedy powiesz:

c is not None

W rzeczywistości sprawdzasz, czy c i None odwołują się do tego samego obiektu. To właśnie robi operator „jest”. W Pythonie None jest specjalną wartością null, co oznacza, że ​​nie masz dostępnej wartości. Sorta jak null w c lub java. Ponieważ Python wewnętrznie przypisuje tylko jedną wartość None, używając operatora „is”, aby sprawdzić, czy coś jest None (myślę, że null) działa, i stał się popularnym stylem. Jednak nie ma to nic wspólnego z wartością prawdziwości zbioru c, chodzi o sprawdzenie, czy c faktycznie jest zbiorem, a nie wartością zerową.

Jeśli chcesz sprawdzić, czy zestaw jest pusty w instrukcji warunkowej, jest rzutowany jako wartość logiczna w kontekście, więc możesz po prostu powiedzieć:

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

Ale jeśli chcesz, aby został przekonwertowany na wartość logiczną, aby był przechowywany, możesz po prostu powiedzieć:

c = set()
c_has_stuff_in_it = bool(c)
Andrew Allaire
źródło
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()
shtut shtuzim
źródło
0

Nie tak czysty jak bool (c), ale był to pretekst do użycia trójskładnika.

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

Używając nieco tej samej logiki, nie ma potrzeby przypisywania do c, chyba że używasz go do czegoś innego.

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

Na koniec założyłbym, że chcesz mieć wartość Prawda / Fałsz, ponieważ zamierzasz wykonać z nią jakiś test boolowski. Zalecałbym pominięcie narzutu wywołania funkcji i definicji, po prostu testując tam, gdzie jest to potrzebne.

Zamiast:

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

Może to:

if a.intersection(b):
    # Do something
Amos Baker
źródło