ตัวอย่างเช่นหากผ่านสิ่งต่อไปนี้:
a = []
ฉันจะตรวจสอบเพื่อดูว่าa
ว่างเปล่าได้อย่างไร
ตัวอย่างเช่นหากผ่านสิ่งต่อไปนี้:
a = []
ฉันจะตรวจสอบเพื่อดูว่าa
ว่างเปล่าได้อย่างไร
คำตอบ:
if not a:
print("List is empty")
การใช้booleanness โดยนัยของความว่างเปล่าlist
นั้นค่อนข้างไพเราะ
if a == []
คือการบังคับประเภทเฉพาะ ( () == []
คือFalse
) นี่ตกลงทั่วไปน่าจะเป็นที่การพิมพ์เป็ดชนะออก (ในผลบอกว่า__nonzero__
เป็นอินเตอร์เฟซสำหรับการทดสอบความว่างเปล่าdocs.python.org/reference/datamodel.html#object.__nonzero__ )
วิธี pythonic ที่จะทำคือจากคู่มือสไตล์ PEP 8 (ที่ใช่หมายถึง "แนะนำ" และไม่ได้หมายความว่า "ไม่แนะนำ"):
สำหรับซีเควนซ์ (สตริง, รายการ, สิ่งอันดับ) ให้ใช้ความจริงที่ว่าลำดับที่ว่างเปล่าเป็นเท็จ
Yes: if not seq: if seq: No: if len(seq): if not len(seq):
seq
คาดว่าจะเป็นวัตถุคล้ายรายการ
ฉันชอบมันมาก:
if len(li) == 0:
print('the list is empty')
วิธีนี้ชัดเจน 100% ซึ่งli
เป็นลำดับ (รายการ) และเราต้องการทดสอบขนาดของมัน ปัญหาของฉันif not li: ...
คือมันให้การแสดงผลที่ผิดพลาดซึ่งli
เป็นตัวแปรบูลีน
li
เป็นคนโง่และไม่สนใจ หากเป็นสิ่งสำคัญคุณควรเพิ่มความคิดเห็นไม่ใช่รหัสเพิ่มเติม
None
หรือ0
เพื่อเพิ่มข้อยกเว้นแทนที่จะผ่าน) ดังนั้นเมื่อคุณทำโดยไม่มีเหตุผลนั่นก็ทำให้เข้าใจผิด - และมันก็หมายความว่าเมื่อรหัสของคุณไม่จำเป็นที่จะต้องสร้างความแตกต่างความแตกต่างจะมองไม่เห็นเพราะคุณได้ "หมาป่าร้องไห้" ทั้งหมดในส่วนที่เหลือของแหล่งที่มา
if bool(len(li) == 0) is True:
?
นี่เป็น google hit ครั้งแรกสำหรับ "python test empty array" และข้อความค้นหาที่คล้ายกันรวมถึงคนอื่น ๆ ดูเหมือนจะสรุปคำถามที่นอกเหนือจากรายการเพียงอย่างเดียวดังนั้นฉันคิดว่าฉันจะเพิ่ม caveat สำหรับลำดับที่แตกต่างกันซึ่งผู้คนจำนวนมาก อาจใช้
คุณต้องระมัดระวังกับอาร์เรย์ NumPy เนื่องจากวิธีการอื่นที่ทำงานได้ดีสำหรับlist
s หรือคอนเทนเนอร์มาตรฐานอื่น ๆ ล้มเหลวสำหรับอาร์เรย์ NumPy ฉันอธิบายว่าทำไมด้านล่าง แต่ในระยะสั้นที่วิธีการที่ต้องการsize
คือการใช้งาน
วิธี "pythonic" ล้มเหลวด้วย NumPy arrays เพราะ NumPy พยายามที่จะส่งอาเรย์ไปยังอาเรย์ของbool
s และif x
พยายามที่จะประเมินทั้งหมดของbool
s ในเวลาเดียวกันสำหรับค่าความจริงรวมบางอย่าง แต่นี่ไม่มีเหตุผลใด ๆ ดังนั้นคุณจะได้รับValueError
:
>>> x = numpy.array([0,1])
>>> if x: print("x")
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
แต่อย่างน้อยกรณีข้างต้นบอกคุณว่ามันล้มเหลว หากคุณมีอาร์เรย์ NumPy ที่มีองค์ประกอบหนึ่งรายการif
คำสั่งจะ "ทำงาน" ในแง่ที่ว่าคุณไม่ได้รับข้อผิดพลาด อย่างไรก็ตามหากองค์ประกอบนั้นเกิดขึ้นเป็น0
(หรือ0.0
, หรือFalse
, ... ) if
คำสั่งจะส่งผลให้ไม่ถูกต้องFalse
:
>>> x = numpy.array([0,])
>>> if x: print("x")
... else: print("No x")
No x
แต่x
มีอยู่อย่างชัดเจนและไม่ว่างเปล่า! ผลลัพธ์นี้ไม่ใช่สิ่งที่คุณต้องการ
len
สามารถให้ผลลัพธ์ที่ไม่คาดคิดตัวอย่างเช่น,
len( numpy.zeros((1,0)) )
ส่งคืน 1 แม้ว่าอาร์เรย์จะมีองค์ประกอบเป็นศูนย์
ตามที่อธิบายไว้ในSciPy FAQวิธีที่ถูกต้องในทุกกรณีที่คุณรู้ว่าคุณมีอาร์เรย์ NumPy คือการใช้if x.size
:
>>> x = numpy.array([0,1])
>>> if x.size: print("x")
x
>>> x = numpy.array([0,])
>>> if x.size: print("x")
... else: print("No x")
x
>>> x = numpy.zeros((1,0))
>>> if x.size: print("x")
... else: print("No x")
No x
หากคุณไม่แน่ใจว่าอาจเป็น A list
, A , NumPy array หรืออย่างอื่นคุณสามารถรวมวิธีการนี้เข้ากับคำตอบที่ @dubiousjim ให้เพื่อให้แน่ใจว่ามีการใช้การทดสอบที่ถูกต้องสำหรับแต่ละประเภท ไม่ "pythonic" มากนัก แต่ปรากฎว่า NumPy จงใจทำลาย pythonicity อย่างน้อยก็ในแง่นี้
หากคุณจำเป็นต้องทำมากกว่าเพียงแค่ตรวจสอบว่าเข้าเป็นที่ว่างเปล่าและคุณกำลังใช้อื่น ๆ NumPy คุณสมบัติเช่นการจัดทำดัชนีหรือคณิตศาสตร์การดำเนินงานก็อาจจะมีประสิทธิภาพมากขึ้น (และแน่นอนร่วมกันมากขึ้น) เพื่อบังคับให้การป้อนข้อมูลจะเป็นอาร์เรย์ NumPy มีฟังก์ชั่นที่ดีบางประการสำหรับการทำเช่นนี้ได้อย่างรวดเร็ว - numpy.asarray
ที่สำคัญที่สุด นี้จะใช้เวลาการป้อนข้อมูลของคุณไม่ทำอะไรเลยถ้ามันมีอยู่แล้วอาร์เรย์หรือตัดการป้อนข้อมูลของคุณลงในอาร์เรย์ถ้าหากมันเป็นรายการ tuple ฯลฯ dtype
และเลือกแปลงไปยังที่คุณเลือก ดังนั้นจึงเป็นไปได้อย่างรวดเร็วมากเมื่อใดก็ตามที่เป็นไปได้และทำให้มั่นใจได้ว่าคุณจะได้รับการป้อนข้อมูลเป็นอาร์เรย์ NumPy เรามักจะใช้ชื่อเดียวกันเนื่องจากการแปลงไปยังอาร์เรย์จะไม่ทำให้มันกลับมานอกขอบเขตปัจจุบัน:
x = numpy.asarray(x, dtype=numpy.double)
นี่จะทำให้การx.size
ตรวจสอบใช้งานได้ในทุกกรณีที่ฉันเห็นในหน้านี้
numpy
- numpy
เป็นห้องสมุดที่มีกรณีการใช้งานที่เฉพาะเจาะจงมากและมีคำจำกัดความ 'ธรรมชาติ' ที่แตกต่างกันของความจริงในอาเรย์ Python มาตรฐานสำหรับตู้คอนเทนเนอร์ มันสมเหตุสมผลที่จะปรับให้เหมาะสมสำหรับกรณีนั้นในลักษณะที่pathlib
ใช้/
ในการเชื่อมโยงเส้นทางแทนที่จะเป็น+
- มันไม่ได้มาตรฐาน แต่สมเหตุสมผลในบริบท
if x
และlen(x)
สำนวน - และบางครั้งความแตกแยกนั้นยากที่จะตรวจจับและตรวจแก้จุดบกพร่อง
วิธีที่ดีที่สุดในการตรวจสอบว่ารายการว่างเปล่า
ตัวอย่างเช่นหากผ่านสิ่งต่อไปนี้:
a = []
ฉันจะตรวจสอบเพื่อดูว่ามีอะไรว่างเปล่าได้อย่างไร
วางรายการในบริบทบูลีน (ตัวอย่างเช่นด้วยคำสั่งif
หรือwhile
) มันจะทดสอบFalse
ว่ามันว่างเปล่าและTrue
อื่น ๆ ตัวอย่างเช่น:
if not a: # do this!
print('a is an empty list')
PEP 8คู่มือแนะนำอย่างเป็นทางการของ Python สำหรับโค้ด Python ในไลบรารี่มาตรฐานของ Python ที่อ้างถึง:
สำหรับซีเควนซ์ (สตริง, รายการ, สิ่งอันดับ) ให้ใช้ความจริงที่ว่าลำดับที่ว่างเปล่าเป็นเท็จ
Yes: if not seq: if seq: No: if len(seq): if not len(seq):
เราควรคาดหวังว่ารหัสไลบรารีมาตรฐานควรมีประสิทธิภาพและถูกต้องที่สุด แต่ทำไมเป็นเช่นนั้นและทำไมเราถึงต้องการแนวทางนี้
ฉันมักจะเห็นโค้ดเช่นนี้จากโปรแกรมเมอร์ที่มีประสบการณ์ใหม่ไปจนถึง Python:
if len(a) == 0: # Don't do this!
print('a is an empty list')
และผู้ใช้ภาษาขี้เกียจอาจถูกล่อลวงให้ทำเช่นนี้:
if a == []: # Don't do this!
print('a is an empty list')
สิ่งเหล่านี้ถูกต้องในภาษาอื่น ๆ ที่เกี่ยวข้อง และสิ่งนี้ก็ถูกต้องทางความหมายใน Python
แต่เราถือว่ามันไม่เป็น Pythonic เพราะ Python สนับสนุนซีแมนทิกส์เหล่านี้โดยตรงในส่วนต่อประสานของวัตถุรายการผ่านการบังคับแบบบูล
จากเอกสาร (และบันทึกการรวมรายการว่างไว้โดยเฉพาะ[]
):
โดยค่าเริ่มต้นวัตถุจะถือว่าเป็นจริงเว้นแต่ว่าระดับของมันจะกำหนด
__bool__()
วิธีการที่จะส่งกลับFalse
หรือ__len__()
วิธีการที่ส่งกลับศูนย์เมื่อเรียกกับวัตถุ นี่คือส่วนใหญ่ของวัตถุในตัวถือว่าเป็นเท็จ:
- ค่าคงที่กำหนดเป็นเท็จ:
None
และFalse
และ- ศูนย์ประเภทตัวเลขใด ๆ :
0
,0.0
,0j
,Decimal(0)
,Fraction(0, 1)
- ลำดับที่ว่างเปล่าและคอลเลกชัน:
''
,()
,[]
,{}
,set()
,range(0)
และเอกสารข้อมูลแบบจำลอง:
เรียกว่าการดำเนินการทดสอบค่าความจริงและตัวในการดำเนินงาน
bool()
; ควรกลับหรือFalse
True
เมื่อไม่ได้กำหนดเมธอดนี้จะ__len__()
ถูกเรียกใช้หากถูกกำหนดไว้และอ็อบเจ็กต์นั้นถูกพิจารณาว่าเป็นจริงถ้าผลลัพธ์ของมันไม่ใช่ศูนย์ หากมีการกำหนดระดับค่า__len__()
มิได้__bool__()
อินสแตนซ์ทั้งหมดได้รับการพิจารณาความจริง
และ
เรียกว่าใช้งานฟังก์ชันใน
len()
ตัว ควรคืนความยาวของวัตถุเป็นจำนวนเต็ม> = 0 นอกจากนี้วัตถุที่ไม่ได้กำหนด__bool__()
วิธีการและ__len__()
วิธีการที่ส่งกลับค่าศูนย์จะถือว่าเป็นเท็จในบริบทบูลีน
ดังนั้นแทนที่จะเป็นเช่นนี้:
if len(a) == 0: # Don't do this!
print('a is an empty list')
หรือสิ่งนี้:
if a == []: # Don't do this!
print('a is an empty list')
ทำเช่นนี้:
if not a:
print('a is an empty list')
มันจ่ายออกหรือไม่ (โปรดทราบว่าใช้เวลาน้อยกว่าในการดำเนินการเทียบเท่าจะดีกว่า :)
>>> import timeit
>>> min(timeit.repeat(lambda: len([]) == 0, repeat=100))
0.13775854044661884
>>> min(timeit.repeat(lambda: [] == [], repeat=100))
0.0984637276455409
>>> min(timeit.repeat(lambda: not [], repeat=100))
0.07878462291455435
สำหรับมาตราส่วนนี่คือค่าใช้จ่ายในการเรียกใช้ฟังก์ชันและการสร้างและส่งคืนรายการเปล่าซึ่งคุณอาจลบออกจากค่าใช้จ่ายของการตรวจสอบความว่างเปล่าที่ใช้ด้านบน:
>>> min(timeit.repeat(lambda: [], repeat=100))
0.07074015751817342
เราจะเห็นว่าทั้งการตรวจสอบสำหรับความยาวที่มีฟังก์ชั่นในตัวlen
เมื่อเทียบกับ0
หรือตรวจสอบกับรายการที่ว่างเปล่าเป็นมากน้อย performant กว่าการใช้ไวยากรณ์ในตัวของภาษาที่เป็นเอกสาร
ทำไม?
สำหรับการ len(a) == 0
ตรวจสอบ:
Python แรกจะต้องตรวจสอบ globals เพื่อดูว่า len
มีเงาหรือไม่
จากนั้นจะต้องเรียกใช้ฟังก์ชันโหลด0
และทำการเปรียบเทียบความเท่าเทียมกันใน Python (แทนที่จะใช้ C):
>>> import dis
>>> dis.dis(lambda: len([]) == 0)
1 0 LOAD_GLOBAL 0 (len)
2 BUILD_LIST 0
4 CALL_FUNCTION 1
6 LOAD_CONST 1 (0)
8 COMPARE_OP 2 (==)
10 RETURN_VALUE
และสำหรับ[] == []
มันจะต้องสร้างรายการที่ไม่จำเป็นจากนั้นทำการเปรียบเทียบในเครื่องเสมือนของ Python อีกครั้ง (ตรงข้ามกับ C)
>>> dis.dis(lambda: [] == [])
1 0 BUILD_LIST 0
2 BUILD_LIST 0
4 COMPARE_OP 2 (==)
6 RETURN_VALUE
วิธี "Pythonic" เป็นการตรวจสอบที่ง่ายและเร็วขึ้นเนื่องจากความยาวของรายการถูกแคชไว้ในส่วนหัวของอินสแตนซ์ของวัตถุ:
>>> dis.dis(lambda: not [])
1 0 BUILD_LIST 0
2 UNARY_NOT
4 RETURN_VALUE
นี่คือส่วนขยายของ
PyObject
ที่เพิ่มob_size
เขตข้อมูล ใช้สำหรับวัตถุที่มีความยาวเท่ากัน ประเภทนี้มักจะไม่ปรากฏใน Python / C API มันสอดคล้องกับเขตข้อมูลที่กำหนดโดยการขยายตัวของPyObject_VAR_HEAD
แมโคร
จากแหล่ง c ในรวม / listobject.h :
typedef struct {
PyObject_VAR_HEAD
/* Vector of pointers to list elements. list[0] is ob_item[0], etc. */
PyObject **ob_item;
/* ob_item contains space for 'allocated' elements. The number
* currently in use is ob_size.
* Invariants:
* 0 <= ob_size <= allocated
* len(list) == ob_size
ผมจะชี้ให้เห็นว่าเรื่องนี้ก็เป็นจริงสำหรับกรณีที่ไม่ว่างเปล่า แต่ที่น่าเกลียดสวยเช่นเดียวกับ
l=[]
แล้ว%timeit len(l) != 0
90.6 ± 8.3 NS NS,%timeit l != []
55.6 NS ± 3.09,%timeit not not l
38.5 NS ± 0.372 แต่ไม่มีทางที่ทุกคนจะเพลิดเพลินไปกับnot not l
ความเร็วสามเท่า มันดูไร้สาระ แต่ความเร็วที่ชนะ
ฉันคิดว่าปัญหาคือการทดสอบด้วย timeit เนื่องจากif l:
มีเพียงพอ แต่%timeit bool(l)
ให้ผลที่น่าประหลาดใจ101 ns ± 2.64 ns ที่น่าสนใจไม่มีทางที่จะบีบบังคับให้บูลโดยไม่มีการลงโทษนี้%timeit l
ไม่มีประโยชน์เนื่องจากไม่มีการแปลงเกิดขึ้น
มายากล IPython %timeit
นั้นไม่ได้ไร้ประโยชน์เลยที่นี่:
In [1]: l = []
In [2]: %timeit l
20 ns ± 0.155 ns per loop (mean ± std. dev. of 7 runs, 100000000 loops each)
In [3]: %timeit not l
24.4 ns ± 1.58 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
In [4]: %timeit not not l
30.1 ns ± 2.16 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
เราสามารถเห็นได้ว่ามีค่าใช้จ่ายเชิงเส้นเล็กน้อยสำหรับค่าใช้จ่ายเพิ่มเติมnot
ที่นี่ เราต้องการที่จะเห็นค่าใช้จ่ายceteris paribusนั่นคือทุกคนเท่ากัน - ที่ทุกคนจะลดลงเท่าที่เป็นไปได้:
In [5]: %timeit if l: pass
22.6 ns ± 0.963 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
In [6]: %timeit if not l: pass
24.4 ns ± 0.796 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
In [7]: %timeit if not not l: pass
23.4 ns ± 0.793 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
ตอนนี้ลองดูกรณีสำหรับรายการที่ไม่มีข้อยกเว้น:
In [8]: l = [1]
In [9]: %timeit if l: pass
23.7 ns ± 1.06 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
In [10]: %timeit if not l: pass
23.6 ns ± 1.64 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
In [11]: %timeit if not not l: pass
26.3 ns ± 1 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
สิ่งที่เราสามารถเห็นได้จากที่นี่คือมันสร้างความแตกต่างเล็กน้อยไม่ว่าคุณจะผ่านการbool
ตรวจสอบสภาพจริงหรือรายชื่อตัวเองและถ้ามีอะไรก็ตาม
Python เขียนด้วย C; มันใช้ตรรกะที่ระดับ C สิ่งที่คุณเขียนด้วย Python จะช้าลง และมันอาจเป็นคำสั่งที่มีขนาดช้ากว่าถ้าคุณไม่ได้ใช้กลไกที่สร้างไว้ใน Python โดยตรง
l=[]
แล้ว%timeit len(l) != 0
90.6 ± 8.3 NS NS, %timeit l != []
55.6 NS ± 3.09, %timeit not not l
38.5 NS ± 0.372 แต่ไม่มีทางที่ทุกคนจะเพลิดเพลินไปกับnot not l
ความเร็วสามเท่า มันดูไร้สาระ แต่ความเร็วชนะออกมา
if l:
มีเพียงพอ แต่%timeit bool(l)
ให้ผลที่น่าประหลาดใจ101 ns ± 2.64 ns ที่น่าสนใจไม่มีทางที่จะบีบบังคับให้บูลโดยไม่มีการลงโทษนี้ %timeit l
ไม่มีประโยชน์เนื่องจากไม่มีการแปลงเกิดขึ้น
รายการเปล่าถือว่าเป็นเท็จในการทดสอบค่าจริง (ดูเอกสารหลาม ):
a = []
if a:
print "not empty"
@Daren Thomas
แก้ไข: อีกจุดหนึ่งที่ต่อต้านการทดสอบรายการที่ว่างเปล่าว่าเป็นเท็จ: แล้วความหลากหลายนั้นเป็นอย่างไร คุณไม่ควรขึ้นอยู่กับรายการที่เป็นรายการ มันควรจะต้มตุ๋นเหมือนเป็ด - คุณจะได้รับเป็ดของคุณได้อย่างไรการต้มตุ๋น '' เท็จ '' เมื่อมันไม่มีองค์ประกอบ?
DuckCollection ของคุณควรนำไปใช้__nonzero__
หรือ__len__
ถ้า a: จะทำงานได้โดยไม่มีปัญหา
[] == False
จะประเมินผลเป็นเท็จได้อย่างไร
bool()
ของค่าการใช้งาน bool([]) == False
จะประเมินให้True
เป็นไปตามที่คาดไว้
คำตอบ (ยอมรับ) ของ Patrickนั้นถูกต้อง: if not a:
เป็นวิธีที่เหมาะสมที่จะทำ คำตอบของ Harley Holcombeนั้นถูกต้องว่านี่เป็นแนวทางใน PEP 8 แต่ไม่มีคำตอบใดที่อธิบายได้ว่าทำไมมันเป็นความคิดที่ดีที่จะทำตามสำนวน - แม้ว่าคุณจะพบว่ามันไม่ชัดเจนหรือสับสนกับผู้ใช้ Ruby หรืออะไรก็ตาม
รหัส Python และชุมชน Python มีสำนวนที่แข็งแกร่งมาก การทำตามสำนวนเหล่านั้นทำให้โค้ดของคุณอ่านง่ายขึ้นสำหรับทุกคนที่มีประสบการณ์ใน Python และเมื่อคุณละเมิดสำนวนเหล่านั้นนั่นเป็นสัญญาณที่ดี
เป็นความจริงที่if not a:
ไม่แยกความแตกต่างของรายการที่ว่างเปล่าNone
หรือตัวเลข 0 หรือ tuples ที่ว่างเปล่าหรือประเภทคอลเลกชันที่ผู้ใช้สร้างขึ้นหรือประเภทที่ไม่ได้สร้างขึ้นโดยผู้ใช้ที่ว่างเปล่าหรืออาร์เรย์ NumPy องค์ประกอบเดียวที่ทำหน้าที่เป็นสเกลา ค่านิยม ฯลฯ และบางครั้งสิ่งสำคัญคือต้องมีความชัดเจนเกี่ยวกับเรื่องนั้น และในกรณีนี้คุณรู้ว่าคุณต้องการชัดเจนอะไรเพื่อให้คุณสามารถทดสอบได้อย่างชัดเจน ตัวอย่างเช่นif not a and a is not None:
หมายถึง "อะไรที่ผิดพลาดยกเว้นไม่มี" ในขณะที่if len(a) != 0:
หมายถึง "เฉพาะลำดับที่ว่างเปล่า - และสิ่งอื่น ๆ นอกเหนือจากลำดับคือข้อผิดพลาดที่นี่" และอื่น ๆ นอกจากการทดสอบสิ่งที่คุณต้องการทดสอบแล้วสิ่งนี้ยังส่งสัญญาณไปยังผู้อ่านว่าการทดสอบนี้มีความสำคัญ
แต่เมื่อคุณไม่มีอะไรที่ชัดเจนเกี่ยวกับสิ่งอื่นใดนอกเหนือจากการif not a:
หลอกลวงผู้อ่าน คุณกำลังส่งสัญญาณบางสิ่งที่สำคัญเมื่อมันไม่ได้เป็น (คุณยังอาจจะทำให้รหัสที่มีความยืดหยุ่นน้อยกว่าหรือช้ากว่าหรืออะไรก็ตาม แต่นั่นคือทั้งหมดที่มีความสำคัญน้อย.) และถ้าคุณเป็นประจำทำให้เข้าใจผิดของผู้อ่านเช่นนี้แล้วเมื่อคุณทำจำเป็นที่จะต้องสร้างความแตกต่างก็จะผ่านเพราะไม่มีใครสังเกตเห็น คุณได้รับ "ร้องไห้หมาป่า" ทั่วรหัสของคุณ
ดูเหมือนจะไม่มีใครถามคำถามที่คุณต้องการทดสอบรายการในตอนแรก เนื่องจากคุณไม่มีบริบทเพิ่มเติมฉันสามารถจินตนาการได้ว่าคุณไม่จำเป็นต้องทำการตรวจสอบในตอนแรก แต่ไม่คุ้นเคยกับการประมวลผลรายการใน Python
ฉันจะเถียงว่าวิธีที่ไพทอนที่สุดคือการไม่ตรวจสอบเลย แต่เป็นการประมวลผลรายการ ด้วยวิธีนี้มันจะทำสิ่งที่ถูกต้องไม่ว่าจะว่างเปล่าหรือเต็ม
a = []
for item in a:
<do something with item>
<rest of code>
สิ่งนี้มีประโยชน์ในการจัดการกับเนื้อหาใด ๆ ของaในขณะที่ไม่ต้องการการตรวจสอบความว่างเปล่าโดยเฉพาะ หากaว่างเปล่าบล็อกที่ขึ้นต่อกันจะไม่ถูกดำเนินการและล่ามจะผ่านไปยังบรรทัดถัดไป
หากคุณต้องการตรวจสอบความว่างเปล่าของอาร์เรย์คำตอบอื่น ๆ ก็เพียงพอแล้ว
<rest of code>
ที่อาจใช้ผลลัพธ์จากการfor
วนซ้ำหรือไม่? โดยตรงหรือใช้ค่าบางอย่างในa
? แน่นอนถ้าสคริปต์ถูกออกแบบให้ทำงานด้วยอินพุตที่ควบคุมอย่างเข้มงวดการตรวจสอบอาจไม่จำเป็นเพียงเล็กน้อย แต่ในกรณีส่วนใหญ่อินพุตจะแตกต่างกันและการตรวจสอบมักจะดีกว่า
len()
เป็นการดำเนินการ O (1)สำหรับรายการ Python, สตริง, dicts และเซต Python ภายในติดตามจำนวนขององค์ประกอบในภาชนะเหล่านี้
JavaScript มีความคิดที่คล้ายกันของ truthy
ฉันได้เขียน:
if isinstance(a, (list, some, other, types, i, accept)) and not a:
do_stuff
ซึ่งได้รับการโหวต -1 ฉันไม่แน่ใจว่าเป็นเพราะผู้อ่านคัดค้านกลยุทธ์หรือคิดว่าคำตอบนั้นไม่เป็นประโยชน์ตามที่นำเสนอ ฉันจะแกล้งทำเป็นว่ามันเป็นช่วงหลังตั้งแต่ --- อะไรก็ตามที่นับว่าเป็น "pythonic" --- นี่คือกลยุทธ์ที่ถูกต้อง ยกเว้นว่าคุณได้ตัดออกไปแล้วหรือเตรียมรับมือกับกรณีที่a
เป็นเช่นFalse
นั้นคุณต้องมีการทดสอบที่เข้มงวดมากกว่าเพียงแค่if not a:
นั้น คุณสามารถใช้สิ่งนี้:
if isinstance(a, numpy.ndarray) and not a.size:
do_stuff
elif isinstance(a, collections.Sized) and not a:
do_stuff
การทดสอบครั้งแรกเป็นการตอบสนองต่อคำตอบของ @ Mike ด้านบน บรรทัดที่สามอาจถูกแทนที่ด้วย:
elif isinstance(a, (list, tuple)) and not a:
หากคุณต้องการที่จะยอมรับอินสแตนซ์ของประเภทเฉพาะ (และประเภทย่อย) หรือด้วย:
elif isinstance(a, (list, tuple)) and not len(a):
คุณสามารถออกไปได้โดยไม่ต้องมีการตรวจสอบประเภทอย่างชัดเจน แต่ถ้าบริบทโดยรอบแล้วทำให้คุณมั่นใจว่าa
เป็นค่าของประเภทที่คุณเตรียมไว้ให้จัดการหรือถ้าคุณแน่ใจว่าประเภทที่คุณไม่พร้อมจะจัดการนั้นกำลังดำเนินอยู่ เพื่อเพิ่มข้อผิดพลาด (เช่นTypeError
ถ้าคุณโทรหาlen
ค่าที่ไม่ได้กำหนดไว้) ที่คุณเตรียมไว้ให้จัดการ โดยทั่วไปการประชุม "pythonic" ดูเหมือนจะเป็นวิธีสุดท้าย บีบมันเหมือนเป็ดแล้วปล่อยมันขึ้นมา DuckError ถ้าไม่รู้วิธีต้มตุ๋น คุณยังคงต้องคิดเกี่ยวกับประเภทของสมมติฐานที่คุณกำลังทำอยู่และไม่ว่ากรณีที่คุณไม่ได้เตรียมที่จะรับมืออย่างถูกต้องนั้นจะเกิดข้อผิดพลาดในที่ที่เหมาะสมหรือไม่ อาร์เรย์ Numpy เป็นตัวอย่างที่ดีที่พึ่งพึ่งการสุ่มสี่สุ่มห้าlen
หรือ typecast บูลีนอาจทำสิ่งที่คุณคาดหวังไม่แม่นยำ
collections.abc.Sized
หรือcollections.abc.Sequence
แต่มันอาจจะเป็นสิ่งที่คุณเขียนเองและregister(list)
ต่อไป หากคุณมีรหัสซึ่งเป็นสิ่งสำคัญที่จะต้องแยกความแตกต่างที่ว่างเปล่าจากความผิดพลาดอื่น ๆ และเพื่อแยกความแตกต่างของรายการและสิ่งอันดับจากลำดับอื่น ๆ สิ่งนี้ถูกต้อง - แต่ฉันไม่เชื่อว่าคุณมีรหัสดังกล่าว
[]
และไม่ใช่สิ่งที่ผิดประเภทอื่น ๆ แน่นอนif a == []:
ว่าถูกเรียกใช้แทนการล้อเล่นกับไอซิส
==
แม้ว่า จากด้านบนของหัวฉันไม่สามารถระบุ[]
ได้ ผลตอบแทนเช่น[] == ()
False
แต่สำหรับตัวอย่างเช่นผลตอบแทนfrozenset()==set()
True
อย่างน้อยก็ให้ความคิดว่าประเภทที่ไม่พึงประสงค์บางประเภทอาจถูกข่มขู่ให้[]
(หรือกลับกัน) เมื่อทำเช่นa == []
นั้น
จากเอกสารเกี่ยวกับการทดสอบค่าความจริง:
ค่าทั้งหมดนอกเหนือจากที่แสดงไว้ที่นี่จะได้รับการพิจารณา True
None
False
0
ตัวอย่างเช่น0.0
, 0j
,''
ตัวอย่างเช่น()
, []
,{}
ยกตัวอย่างเช่น__bool__()
หรือ__len__()
เมธอดเมื่อเมธอดนั้นส่งคืนค่าเลขศูนย์หรือค่าบูFalse
ลดังที่เห็นได้รายการว่างเปล่า[]
เป็นเท็จดังนั้นการทำสิ่งที่ควรทำกับค่าบูลีนฟังดูมีประสิทธิภาพมากที่สุด:
if not a:
print('"a" is empty!')
assert(not myList)
ใช้เพียงแค่ หากคุณยังต้องการที่จะยืนยันวัตถุนั้นเป็นคุณสามารถใช้list
assertIsInstance()
คุณสามารถตรวจสอบว่ารายการว่างเปล่าหรือไม่:
a = [] #the list
1)วิธี pythonic ที่ค่อนข้างเรียบง่าย:
if not a:
print("a is empty")
ในหลาม, ภาชนะเปล่าเช่นรายการ tuples, ชุด dicts ตัวแปรอื่น ๆ False
จะเห็นเป็น เราสามารถจัดการกับรายการเป็นเพรดิเคต ( ส่งคืนค่าบูลีน ) และTrue
ค่าจะบ่งบอกว่ามันไม่ว่างเปล่า
2)วิธีที่ชัดเจนมาก: การใช้len()
เพื่อค้นหาความยาวและตรวจสอบว่ามันเท่ากับ0
:
if len(a) == 0:
print("a is empty")
3)หรือเปรียบเทียบกับรายการว่างที่ไม่ระบุชื่อ:
if a == []:
print("a is empty")
4)อีกเลยโง่วิธีที่จะทำคือการใช้exception
และiter()
:
try:
next(iter(a))
# list has elements
except StopIteration:
print("Error: a is empty")
ฉันชอบสิ่งต่อไปนี้:
if a == []:
print "The list is empty."
if not a:
และแตกหักง่ายกว่า โปรดอย่าทำ
() == []
นี้ยังเท่ากับเท็จ แม้ว่าฉันจะชอบวิธีการใช้งานนี้if not a:
ครอบคลุมทุกกรณี แต่ถ้าคุณคาดหวังว่ารายการนั้นเป็นตัวอย่างที่ดีของคุณ
วิธีที่ 1 (ที่ต้องการ):
if not a :
print ("Empty")
วิธีที่ 2:
if len(a) == 0 :
print( "Empty" )
วิธีที่ 3:
if a == [] :
print ("Empty")
def list_test (L):
if L is None : print('list is None')
elif not L : print('list is empty')
else: print('list has %d elements' % len(L))
list_test(None)
list_test([])
list_test([1,2,3])
บางครั้งเป็นการดีที่จะทดสอบNone
และแยกว่างเปล่าเนื่องจากเป็นสถานะที่แตกต่างกันสองสถานะ รหัสด้านบนสร้างผลลัพธ์ต่อไปนี้:
list is None
list is empty
list has 3 elements
แม้ว่ามันจะไม่มีค่าอะไรที่None
เป็นเท็จ ดังนั้นหากคุณไม่ต้องการแยกการทดสอบเพื่อความNone
สมบูรณ์คุณไม่จำเป็นต้องทำเช่นนั้น
def list_test2 (L):
if not L : print('list is empty')
else: print('list has %d elements' % len(L))
list_test2(None)
list_test2([])
list_test2([1,2,3])
คาดว่าจะผลิต
list is empty
list is empty
list has 3 elements
มีคำตอบมากมายและหลายคนก็ค่อนข้างดี ฉันแค่อยากจะเพิ่มการตรวจสอบว่า
not a
จะผ่านNone
และโครงสร้างที่ว่างเปล่าประเภทอื่น ๆ หากคุณต้องการตรวจสอบรายการว่างคุณสามารถทำสิ่งนี้ได้:
if isinstance(a, list) and len(a)==0:
print("Received an empty list")
a
ไม่ใช่รายการและa
ไม่มีวิธีการ__len__
ใช้ ฉันจะแนะนำ:if isinstance(obj, list): if len(obj) == 0: print '...'
and
ขี้เกียจใน Python จะไม่มีการดำเนินการใด ๆ หลังจากand
นั้นหากเงื่อนไขก่อนหน้าand
นี้เป็นเท็จ
เราสามารถใช้ง่ายถ้าอื่น:
item_list=[]
if len(item_list) == 0:
print("list is empty")
else:
print("list is not empty")
หากคุณต้องการตรวจสอบว่ารายการว่างเปล่าหรือไม่:
l = []
if l:
# do your stuff.
หากคุณต้องการตรวจสอบว่าค่าทั้งหมดในรายการว่างเปล่า อย่างไรก็ตามมันจะTrue
เป็นรายการที่ว่างเปล่า:
l = ["", False, 0, '', [], {}, ()]
if all(bool(x) for x in l):
# do your stuff.
หากคุณต้องการใช้ทั้งสองกรณีพร้อมกัน:
def empty_list(lst):
if len(lst) == 0:
return False
else:
return all(bool(x) for x in l)
ตอนนี้คุณสามารถใช้:
if empty_list(lst):
# do your stuff.
ด้วยแรงบันดาลใจจากวิธีการแก้ปัญหาของ @dubiousjim ฉันเสนอให้ใช้การตรวจสอบทั่วไปเพิ่มเติมว่าเป็นสิ่งที่ทำซ้ำได้หรือไม่
import collections
def is_empty(a):
return not a and isinstance(a, collections.Iterable)
หมายเหตุ: สตริงถูกพิจารณาว่าสามารถทำซ้ำได้ - เพิ่มand not isinstance(a,(str,unicode))
ถ้าคุณต้องการยกเว้นสตริงว่างที่จะถูกแยกออก
ทดสอบ:
>>> is_empty('sss')
False
>>> is_empty(555)
False
>>> is_empty(0)
False
>>> is_empty('')
True
>>> is_empty([3])
False
>>> is_empty([])
True
>>> is_empty({})
True
>>> is_empty(())
True
if a:
ก็คงเป็นเพราะฉันต้องการข้อยกเว้นถ้าa
ไม่มีคอนเทนเนอร์ (การทำซ้ำยังช่วยให้ผู้ทำซ้ำซึ่งไม่สามารถทดสอบความว่างเปล่าได้อย่างเป็นประโยชน์)
print('not empty' if a else 'empty')
ปฏิบัติมากขึ้นเล็กน้อย:
a.pop() if a else None
และรุ่นที่สั้นที่สุด:
if a: a.pop()
ตั้งแต่ python3 เป็นต้นไปคุณสามารถใช้
a == []
เพื่อตรวจสอบว่ารายการว่างเปล่า
แก้ไข: มันใช้งานได้กับ python2.7 เช่นกัน
ฉันไม่แน่ใจว่าทำไมมีคำตอบที่ซับซ้อนมากมาย มันค่อนข้างชัดเจนและตรงไปตรงมา
a
ว่างเปล่าหรือไม่
pythonic
a==[]
มันจะพิมพ์จริงบนเทอร์มินัลไพ ธ อนถ้า a ว่างเปล่า มิฉะนั้นจะพิมพ์ False คุณสามารถใช้สิ่งนี้ภายในเงื่อนไข if as asif(a==[])
คุณสามารถลองใช้บูล () เช่นนี้
a = [1,2,3];
print bool(a); # it will return True
a = [];
print bool(a); # it will return False
ฉันชอบวิธีนี้สำหรับการตรวจสอบรายการว่างเปล่าหรือไม่
มีประโยชน์มากและมีประโยชน์
bool()
แปลงตัวแปร Python เป็นบูลีนเพื่อให้คุณสามารถเก็บค่าความจริงหรือความผิดพลาดของค่าโดยไม่ต้องใช้คำสั่ง if ฉันคิดว่ามันอ่านง่ายกว่าการใช้เงื่อนไขแบบเดียวกับคำตอบที่ยอมรับ แต่ฉันแน่ใจว่ามีกรณีการใช้ที่ดีอื่น ๆ
เพียงใช้ is_empty () หรือทำให้ฟังก์ชั่นที่ชอบ: -
def is_empty(any_structure):
if any_structure:
print('Structure is not empty.')
return True
else:
print('Structure is empty.')
return False
มันสามารถใช้สำหรับ data_structure ใด ๆ เช่นรายการ tuples พจนานุกรมและอื่น ๆ อีกมากมาย is_empty(any_structure)
โดยเหล่านี้คุณสามารถเรียกมันหลายครั้งโดยใช้เพียง
is_empty
แนะนำว่าจะส่งคืนบางสิ่ง แต่ถ้าเป็นเช่นนั้นสิ่งนั้นจะเป็นbool(any_structure)
สิ่งที่คุณควรใช้แทน ( เมื่อคุณต้องการbool
เลย)
bool
(เช่น) พิมพ์ข้อความไปยังเอาต์พุตมาตรฐาน
bool
ตัวแปรส่งคืน ทางเลือกเป็นของคุณ ฉันเขียนทั้งสองเพื่อให้คุณสามารถเลือกระหว่างพวกเขา
วิธีง่ายๆคือการตรวจสอบความยาวเท่ากับศูนย์
if len(a) == 0:
print("a is empty")
ค่าความจริงของรายการที่ว่างเปล่าคือในขณะที่สำหรับรายการที่ไม่ว่างเปล่ามันเป็นFalse
True
สิ่งที่นำฉันมาที่นี่คือกรณีใช้งานพิเศษ: ฉันต้องการให้ฟังก์ชันบอกฉันว่ารายการว่างเปล่าหรือไม่ ฉันต้องการหลีกเลี่ยงการเขียนฟังก์ชั่นของตัวเองหรือใช้การแสดงออกแลมบ์ดาที่นี่ (เพราะดูเหมือนว่ามันควรจะง่ายพอ):
foo = itertools.takewhile(is_not_empty, (f(x) for x in itertools.count(1)))
และแน่นอนมีวิธีที่เป็นธรรมชาติมากที่จะทำ:
foo = itertools.takewhile(bool, (f(x) for x in itertools.count(1)))
แน่นอนไม่ได้ใช้bool
ในif
(คือif bool(L):
) เพราะโดยนัย แต่สำหรับกรณีที่ "ไม่ว่าง" มีความจำเป็นอย่างชัดเจนว่าเป็นฟังก์ชั่นbool
เป็นตัวเลือกที่ดีที่สุด
ในการตรวจสอบว่ารายการว่างเปล่าหรือไม่คุณสามารถใช้สองวิธีต่อไปนี้ แต่จำไว้ว่าเราควรหลีกเลี่ยงวิธีการตรวจสอบลำดับอย่างชัดเจน (เป็น
less pythonic
วิธี):
def enquiry(list1):
if len(list1) == 0:
return 0
else:
return 1
# ––––––––––––––––––––––––––––––––
list1 = []
if enquiry(list1):
print ("The list isn't empty")
else:
print("The list is Empty")
# Result: "The list is Empty".
วิธีที่สองคือ
more pythonic
หนึ่ง วิธีนี้เป็นวิธีการตรวจสอบโดยนัยและเป็นที่นิยมมากกว่าวิธีก่อนหน้า
def enquiry(list1):
if not list1:
return True
else:
return False
# ––––––––––––––––––––––––––––––––
list1 = []
if enquiry(list1):
print ("The list is Empty")
else:
print ("The list isn't empty")
# Result: "The list is Empty"
หวังว่านี่จะช่วยได้