Mengembalikan boolean jika set kosong

97

Saya berjuang untuk menemukan cara yang lebih bersih untuk mengembalikan nilai boolean jika set saya kosong di akhir fungsi saya

Saya mengambil persimpangan dua set, dan ingin mengembalikan Trueatau Falseberdasarkan jika set yang dihasilkan kosong.

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

Pikiran awal saya adalah melakukannya

return c is not None

Namun, dalam interpreter saya, saya dapat dengan mudah melihat bahwa pernyataan itu akan kembali menjadi true jika c = set([])

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

Saya juga mencoba semua yang berikut ini:

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

Sekarang saya sudah membaca dari dokumentasi bahwa saya hanya dapat menggunakan and, ordan notdengan himpunan kosong untuk menyimpulkan nilai boolean. Sejauh ini, satu-satunya hal yang bisa saya pikirkan adalah kembali bukan c

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

Saya merasa ada cara yang jauh lebih pythonic untuk melakukan ini, dengan saya berjuang untuk menemukannya. Saya tidak ingin mengembalikan kumpulan aktual ke pernyataan if karena saya tidak membutuhkan nilainya, saya hanya ingin tahu apakah nilainya berpotongan.

CB
sumber
4
set kosong dianggap boolean. False equivalent jika Anda memasukkannya seperti itu:bool(set([]))
woozyking
3
omong-omong, pertanyaan yang dikerjakan dengan sangat baik, yang luar biasa.
Jonas Schäfer
@JonasWielicki Terima kasih! Hargai jawabannya - ketahuilah bahwa itu adalah sesuatu yang seperti itu.
CB
Pertanyaan ini akan berubah menjadi 5 tahun dan tidak ada yang menyarankan untuk menggunakan isdisjoint. Saya sangat terkejut.
Adirio

Jawaban:

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

bool()akan melakukan sesuatu yang mirip not not, tetapi lebih ideomatis dan jelas.

Jonas Schäfer
sumber
7
Saya keberatan, tulisan bool(...)saat Anda bertanya is_emptytidak jelas. Saya tidak mengungkapkan maksudnya.
tamas.kenez
2
@ tamas.kenez Anda harus mengakui, bahwa ini lebih jelas dari not not;). (FTR: Saya sudah memberi suara positif pada jawaban @gefeis, tetapi saya tidak memiliki pengaruh pada hal yang diterima OP…)
Jonas Schäfer
109

bukan sebagai pythonic seperti jawaban lainnya, tetapi matematika:

return len(c) == 0

Karena beberapa komentar bertanya-tanya tentang dampaknya len(set)terhadap kompleksitas. Ini adalah O (1) seperti yang ditunjukkan dalam kode sumber yang diberikan bergantung pada variabel yang melacak penggunaan himpunan.

static Py_ssize_t
set_len(PyObject *so)
{
    return ((PySetObject *)so)->used;
}
gefei
sumber
9
Saya pikir ini sebenarnya lebih baik. Itu memperjelas apa maksud Anda.
arshajii
4
Saya khawatir ini harus menghitung len(c)meskipun csangat besar, yang tidak perlu untuk memeriksa kekosongan.
Michele De Pascalis
1
@Glaedr Saya percaya pada cpython len untuk struktur data yang umum digunakan (yaitu daftar, set) adalah O (1) (yaitu mereka menyimpan variabel pada struktur data yang mewakili panjangnya)
CB
2
^ +1 @CB saya melakukan beberapa tes pada len (c) dan itu pasti beberapa variabel yang mewakili len karena ada perbedaan runtime yang dapat diabaikan ketika ukuran yang ditetapkan mengubah urutan dramatis besarnya.
dster77
1
@ dster77 saya membuat profil kode saya dengan kedua versi dan secara signifikan lebih cepat bila dibandingkan dengan set()(python 3.5.2 di windows)
mathiasfk
23

Jika Anda ingin return Truemengosongkan set, maka saya pikir akan lebih jelas untuk dilakukan:

return c == set()

yaitu " csama dengan yang kosong set".

(Atau, untuk sebaliknya, return c != set()).

Menurut pendapat saya, ini lebih eksplisit (meskipun kurang idiomatis) daripada mengandalkan interpretasi Python dari himpunan kosong seperti Falsedalam konteks boolean.

jonrsharpe
sumber
2
Sebenarnya, mengandalkan interpretasi Python adalah praktik yang sangat dapat diterima. Selama keterbatasannya diperhatikan.
gunung berapi
17

Jika cadalah satu set maka Anda dapat memeriksa apakah itu kosong dengan melakukan: return not c.

Jika ckosong maka not cakan True.

Jika tidak, jika cmengandung elemen apa pun not cakan False.

Simeon Visser
sumber
6

Saat Anda mengatakan:

c is not None

Anda sebenarnya memeriksa apakah c dan None mereferensikan objek yang sama. Itulah yang dilakukan oleh operator "adalah". Dalam python, None adalah nilai null khusus yang secara konvensional berarti Anda tidak memiliki nilai yang tersedia. Agak seperti null di c atau java. Karena python secara internal hanya memberikan satu nilai None menggunakan operator "is" untuk memeriksa apakah ada sesuatu yang Tidak Ada (pikirkan null) berfungsi, dan itu telah menjadi gaya yang populer. Namun ini tidak ada hubungannya dengan nilai kebenaran dari himpunan c, ini memeriksa bahwa c sebenarnya adalah himpunan daripada nilai null.

Jika Anda ingin memeriksa apakah suatu set kosong dalam pernyataan bersyarat, itu dilemparkan sebagai boolean dalam konteks sehingga Anda bisa mengatakan:

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

Tetapi jika Anda ingin itu diubah menjadi boolean untuk disimpan, Anda cukup mengatakan:

c = set()
c_has_stuff_in_it = bool(c)
Andrew Allaire
sumber
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
sumber
0

Tidak sebersih bool (c) tapi itu alasan untuk menggunakan terner.

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

Juga menggunakan sedikit logika yang sama, tidak perlu menetapkan ke c kecuali Anda menggunakannya untuk hal lain.

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

Akhirnya, saya akan berasumsi Anda menginginkan nilai True / False karena Anda akan melakukan semacam uji boolean dengannya. Saya akan merekomendasikan untuk melewatkan overhead panggilan fungsi dan definisi dengan hanya menguji di mana Anda membutuhkannya.

Dari pada:

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

Mungkin ini:

if a.intersection(b):
    # Do something
Amos Baker
sumber