Câu hỏi Làm cách nào để kiểm tra xem danh sách có trống không?


Ví dụ: nếu vượt qua các điều sau:

a = []

Làm cách nào để kiểm tra xem liệu a trống không?


2729
2017-09-10 06:20


gốc




Các câu trả lời:


if not a:
  print("List is empty")

Sử dụng booleanness tiềm ẩn của danh sách trống là khá pythonic.


3907
2017-09-10 06:28



Chơi chủ trương của quỷ. Tôi không hiểu tại sao thành ngữ này được coi là pythonic. 'Rõ ràng là tốt hơn sau đó ngầm', đúng không? Kiểm tra này dường như không rõ ràng về những gì đang kiểm tra. - James McMahon
@JamesMcMahon - đó là một sự cân bằng giữa tính giải thích và tính linh hoạt của loại. nói chung, "rõ ràng" có nghĩa là không làm những điều "huyền diệu". mặt khác, "gõ vịt" có nghĩa là làm việc với nhiều giao diện chung hơn là kiểm tra rõ ràng các loại. một cái gì đó như if a == [] đang buộc một loại cụ thể (() == [] Là False). ở đây, sự đồng thuận chung dường như là cách gõ vịt thắng (có hiệu lực, nói rằng __nonzero__ là giao diện để kiểm tra tính trống rỗng docs.python.org/reference/datamodel.html#object.__nonzero__) - andrew cooke
Điều này được ghi nhận trong phần Đề xuất lập trình của PEP 8: "Đối với chuỗi, (chuỗi, danh sách, bộ dữ liệu), sử dụng thực tế là các chuỗi rỗng là sai." - abarnert
ValueError: Giá trị thực của một mảng có nhiều hơn một phần tử không rõ ràng. Sử dụng a.any () hoặc a.all () Tôi thấy lỗi này bất cứ khi nào mảng có thứ gì đó trong đó - PirateApp
@PireattApp, bạn phải sử dụng Numpy. Họ đang nói về mảng thông thường. Đối với numpy, có thể bạn muốn sử dụng 'không phải là Không có gì'? - Sam Bobel


Cách nhiệt tình để làm điều đó là từ Hướng dẫn về phong cách PEP 8 (Ở đâu Vâng có nghĩa là "được đề xuất" và Không có nghĩa là "không được khuyến nghị"):

Đối với các chuỗi, (chuỗi, danh sách, bộ dữ liệu), sử dụng thực tế là các chuỗi rỗng là sai.   

Vâng: if not seq:
     if seq:

Không:  if len(seq):
     if not len(seq):

865
2017-09-10 10:33



Cách thứ hai có vẻ tốt hơn nếu bạn muốn báo hiệu seq được mong đợi là một loại đối tượng giống như danh sách. - BallpointBen
@BallpointBen đó, những người ủng hộ Python sẽ nói, nên được ngầm định trong cách biến được đặt tên, càng nhiều càng tốt - Aalok


Tôi thích nó một cách rõ ràng:

if len(li) == 0:
    print('the list is empty')

Bằng cách này, rõ ràng là 100% li là một chuỗi (danh sách) và chúng tôi muốn kiểm tra kích thước của nó. Vấn đề của tôi với if not li: ... là nó cho ấn tượng sai lầm rằng li là một biến boolean.


519
2017-09-05 00:30



Kiểm tra xem độ dài của một danh sách có bằng không, thay vì chỉ kiểm tra xem danh sách có sai không, là xấu và không gây hại. Bất cứ ai quen thuộc với Python sẽ không nghĩ li là một bool ở tất cả, và sẽ không quan tâm. Nếu điều quan trọng là bạn nên thêm nhận xét chứ không phải thêm mã. - Carl Smith
Điều này có vẻ giống như một bài kiểm tra chính xác không cần thiết, thường chậm hơn và luôn luôn ít có thể đọc được IMHO. Thay vì kiểm tra kích thước của một cái gì đó trống rỗng, tại sao không chỉ kiểm tra nếu nó có sản phẩm nào? - John B
Dù sao, lý do này là xấu (và rằng thành ngữ vi phạm trong một ngôn ngữ với thành ngữ mạnh mẽ như Python là xấu nói chung) là nó báo hiệu cho người đọc rằng bạn đặc biệt kiểm tra độ dài vì lý do nào đó (ví dụ, bởi vì bạn muốn None hoặc là 0 để đưa ra một ngoại lệ hơn là vượt qua). Vì vậy, khi bạn làm điều đó không có lý do, đó là gây hiểu nhầm - và nó cũng có nghĩa là khi mã của bạn làm cần phải làm cho sự khác biệt, sự khác biệt là vô hình bởi vì bạn đã "khóc sói" trên tất cả các phần còn lại của nguồn. - abarnert
Tôi nghĩ đây chỉ là việc kéo dài mã không cần thiết. Nếu không, tại sao thậm chí không còn "rõ ràng" với if bool(len(li) == 0) is True:? - augurar
@Jabba nó sẽ là O (1) trong nhiều trường hợp (những nơi bạn làm việc với các kiểu dữ liệu tích hợp), nhưng bạn không thể dựa vào đó. Bạn có thể đang làm việc với loại dữ liệu tùy chỉnh không có thuộc tính này. Bạn cũng có thể quyết định thêm kiểu dữ liệu tùy chỉnh này sau, sau khi bạn đã viết mã này. - ralokt


Những người khác dường như đang khái quát câu hỏi ngoài danh sách, vì vậy tôi nghĩ tôi sẽ thêm một cảnh báo cho một loại trình tự khác nhau mà nhiều người có thể sử dụng, đặc biệt vì đây là lần truy cập đầu tiên của google cho "python test empty array" .

Các phương pháp khác không hoạt động đối với mảng có nhiều mảng

Bạn cần phải cẩn thận với các mảng cứng nhắc, bởi vì các phương pháp khác hoạt động tốt cho lists hoặc các thùng chứa tiêu chuẩn khác không thành công đối với mảng có nhiều mảng. Tôi giải thích lý do tại sao dưới đây, nhưng trong ngắn hạn, phương pháp ưa thích là để sử dụng size.

Cách "pythonic" không hoạt động: Phần 1

Cách "pythonic" không thành công với mảng numpy bởi vì cố gắng numpy để đưa mảng vào một mảng boolcát if x cố gắng đánh giá tất cả những bools cùng một lúc cho một số loại giá trị chân lý tổng hợp. Nhưng điều này không có ý nghĩa gì, vì vậy bạn sẽ có 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()

Cách "pythonic" không hoạt động: Phần 2

Nhưng ít nhất trường hợp trên cho bạn biết rằng nó không thành công. Nếu bạn tình cờ có một mảng numpy với chính xác một phần tử, if tuyên bố sẽ "làm việc", theo nghĩa là bạn không gặp lỗi. Tuy nhiên, nếu một yếu tố đó xảy ra 0 (hoặc là 0.0, hoặc là false, ...), các if tuyên bố sẽ không chính xác dẫn đến false:

>>> x = numpy.array([0,])
>>> if x: print("x")
... else: print("No x")
No x

Nhưng rõ ràng x tồn tại và không trống! Kết quả này không phải là những gì bạn muốn.

Sử dụng len có thể cho kết quả bất ngờ

Ví dụ,

len( numpy.zeros((1,0)) )

trả về 1, mặc dù mảng có 0 phần tử.

Cách numpythonic

Như đã giải thích trong scipy FAQ, phương pháp chính xác trong mọi trường hợp mà bạn biết bạn có một mảng numpy là sử dụng 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

Nếu bạn không chắc chắn liệu nó có thể là list, một mảng numpy, hoặc cái gì khác, bạn có thể kết hợp cách tiếp cận này với câu trả lời @dubiousjim cho để đảm bảo kiểm tra đúng được sử dụng cho từng loại. Không phải là rất "pythonic", nhưng nó chỉ ra rằng numpy cố ý phá vỡ pythonicity trong ít nhất là ý nghĩa này.

Nếu bạn cần làm nhiều hơn là chỉ kiểm tra xem đầu vào có trống không và bạn đang sử dụng các tính năng khác như lập chỉ mục hoặc hoạt động toán, thì có thể hiệu quả hơn (và chắc chắn hơn) để ép đầu vào được một mảng numpy. Có một vài chức năng tốt để thực hiện điều này nhanh chóng - quan trọng nhất numpy.asarray. Điều này có đầu vào của bạn, không có gì nếu nó đã là một mảng, hoặc kết thúc tốt đẹp đầu vào của bạn vào một mảng nếu đó là một danh sách, tuple, vv, và tùy chọn chuyển đổi nó thành lựa chọn của bạn dtype. Vì vậy, nó rất nhanh chóng bất cứ khi nào nó có thể được, và nó đảm bảo rằng bạn chỉ nhận được để giả định đầu vào là một mảng numpy. Chúng tôi thường thậm chí chỉ sử dụng cùng một tên, vì việc chuyển đổi thành một mảng sẽ không làm cho nó trở lại bên ngoài hiện tại phạm vi:

x = numpy.asarray(x, dtype=numpy.double)

Điều này sẽ làm cho x.size kiểm tra công việc trong mọi trường hợp tôi thấy trên trang này.


209
2018-02-21 16:48



Cần lưu ý rằng đây không phải là một lỗ hổng trong Python, mà là một sự phá vỡ hợp đồng có chủ đích bởi numpy - - numpy là một thư viện với một trường hợp sử dụng rất cụ thể, và nó có một định nghĩa 'tự nhiên' khác nhau về độ trung thực của một mảng là tiêu chuẩn Python cho các thùng chứa. Nó có ý nghĩa để tối ưu hóa cho trường hợp đó, theo cách mà pathlib sử dụng / để ghép các đường dẫn thay vì + - nó không chuẩn, nhưng có ý nghĩa trong ngữ cảnh. - Gareth Latty
Đã đồng ý. Quan điểm của tôi chỉ là điều quan trọng cần nhớ là numpy đã thực hiện sự lựa chọn để phá vỡ gõ vịt cho cả hai rất phổ biến if x và len(x) thành ngữ - và đôi khi vỡ có thể rất khó phát hiện và gỡ lỗi. - Mike
Tôi không biết, đối với tôi, nếu một phương pháp gọi là len (x) không trả về độ dài mảng vì các giả định, nó được thiết kế xấu. - Dalton
Câu hỏi này không liên quan gì đến mảng numpy - ppperry
@ pperry Có, câu hỏi ban đầu không phải là về mảng Numpy, nhưng khi làm việc với những người và có thể là đối số gõ vịt, câu hỏi này trở nên rất có liên quan. - peterhil


Danh sách trống được coi là sai trong thử nghiệm giá trị thực (xem tài liệu python):

a = []
if a:
     print "not empty"

@Daren Thomas

EDIT: Một điểm chống lại thử nghiệm   danh sách trống là False: Còn về   đa hình? Bạn không nên phụ thuộc vào   một danh sách là một danh sách. Nó chỉ nên   quack như vịt - bạn thế nào   để có được duckCollection của bạn để quack   '' Sai '' khi nó không có phần tử?

DuckCollection của bạn nên triển khai __nonzero__ hoặc là __len__ do đó, nếu a: sẽ làm việc mà không có vấn đề gì.


104
2017-09-10 06:31





Cách tốt nhất để kiểm tra xem danh sách có trống không

Ví dụ: nếu vượt qua các điều sau:

a = []

Làm cách nào để kiểm tra xem liệu có trống không?

Câu trả lời ngắn:

Đặt danh sách trong ngữ cảnh boolean (ví dụ, với một if hoặc là while tuyên bố). Nó sẽ kiểm tra False nếu nó trống, và True nếu không thì. Ví dụ:

if not a:                           # do this!
    print('a is an empty list')

Kháng cáo lên thẩm quyền

PEP 8, hướng dẫn kiểu Python chính thức cho mã Python trong thư viện chuẩn của Python, xác nhận:

Đối với các chuỗi, (chuỗi, danh sách, bộ dữ liệu), sử dụng thực tế là các chuỗi rỗng là sai.

Yes: if not seq:
     if seq:

No: if len(seq):
    if not len(seq):

Chúng ta nên mong đợi rằng mã thư viện chuẩn nên được thực hiện và chính xác nhất có thể. Nhưng tại sao lại là trường hợp đó, và tại sao chúng ta cần hướng dẫn này?

Giải trình

Tôi thường xuyên thấy mã như thế này từ những lập trình viên có kinh nghiệm mới với Python:

if len(a) == 0:                     # Don't do this!
    print('a is an empty list')

Và người dùng ngôn ngữ lười biếng có thể bị cám dỗ để làm điều này:

if a == []:                         # Don't do this!
    print('a is an empty list')

Đây là chính xác trong các ngôn ngữ khác của họ. Và điều này thậm chí còn đúng ngữ nghĩa trong Python.

Nhưng chúng ta coi nó không phải Pythonic vì Python hỗ trợ các ngữ nghĩa này trực tiếp trong giao diện của đối tượng danh sách thông qua cưỡng chế boolean.

Từ tài liệu (và lưu ý cụ thể việc bao gồm danh sách trống, []):

Theo mặc định, một đối tượng được coi là đúng trừ khi lớp của nó được định nghĩa   cũng là một __bool__() phương thức trả về False hoặc một __len__() phương pháp   trả về số không, khi được gọi với đối tượng. Dưới đây là hầu hết các đối tượng tích hợp được xem là sai:

  • hằng số được định nghĩa là sai: None và False.
  • không thuộc bất kỳ loại số nào: 0, 0.0, 0j, Decimal(0), Fraction(0, 1)
  • chuỗi và bộ sưu tập trống: '', (), [], {}, set(), range(0)

Và tài liệu datamodel:

object.__bool__(self)

Được gọi để thực hiện kiểm tra giá trị sự thật và hoạt động tích hợp bool(); nên quay trở lại False hoặc là True. Khi phương pháp này không được xác định,    __len__() được gọi, nếu nó được xác định, và đối tượng được coi là đúng nếu kết quả của nó là nonzero. Nếu một lớp xác định cả hai __len__()   cũng không __bool__(), tất cả các trường hợp của nó được coi là đúng sự thật.

object.__len__(self)

Được gọi để triển khai chức năng tích hợp len(). Nên trả về độ dài của đối tượng, một số nguyên> = 0. Ngoài ra, một đối tượng không xác định __bool__() phương pháp và có __len__() phương thức trả về số không được coi là sai trong ngữ cảnh Boolean.

Vì vậy, thay vì điều này:

if len(a) == 0:                     # Don't do this!
    print('a is an empty list')

hoặc điều này:

if a == []:                     # Don't do this!
    print('a is an empty list')

Làm cái này:

if not a:
    print('a is an empty list')

Làm những gì Pythonic thường trả hết hiệu suất:

Nó có trả hết không? (Lưu ý rằng ít thời gian hơn để thực hiện một phép toán tương đương là tốt hơn :)

>>> 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

Đối với tỷ lệ, đây là chi phí gọi hàm và xây dựng và trả về một danh sách trống, bạn có thể trừ chi phí của các kiểm tra trống rỗng được sử dụng ở trên:

>>> min(timeit.repeat(lambda: [], repeat=100))
0.07074015751817342

Chúng ta thấy rằng hoặc kiểm tra độ dài với hàm dựng sẵn len so với 0  hoặc là việc kiểm tra danh sách trống là nhiều kém hiệu quả hơn việc sử dụng cú pháp dựng sẵn của ngôn ngữ như được ghi lại.

Tại sao?

Cho len(a) == 0 kiểm tra:

Python đầu tiên phải kiểm tra các hình cầu để xem len bị che khuất.

Sau đó, nó phải gọi hàm, tải 0và thực hiện so sánh bình đẳng bằng Python (thay vì bằng 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

Và cho [] == [] nó phải xây dựng một danh sách không cần thiết và sau đó, một lần nữa, thực hiện thao tác so sánh trong máy ảo của Python (trái ngược với C)

>>> dis.dis(lambda: [] == [])
  1           0 BUILD_LIST               0
              2 BUILD_LIST               0
              4 COMPARE_OP               2 (==)
              6 RETURN_VALUE

Cách "Pythonic" là một kiểm tra đơn giản hơn và nhanh hơn nhiều vì độ dài của danh sách được lưu trữ trong tiêu đề đối tượng thể hiện:

>>> dis.dis(lambda: not [])
  1           0 BUILD_LIST               0
              2 UNARY_NOT
              4 RETURN_VALUE

Bằng chứng từ nguồn và tài liệu C

PyVarObject

Đây là phần mở rộng của PyObject thêm rằng ob_size cánh đồng. Điều này chỉ được sử dụng cho các đối tượng có một số khái niệm về chiều dài. Loại này thường không xuất hiện trong API Python / C. Nó tương ứng với các trường được xác định bởi việc mở rộng PyObject_VAR_HEAD macro.

Từ nguồn c trong Bao gồm / 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

Tôi rất thích nghiên cứu điều này và tôi dành rất nhiều thời gian để sắp xếp các câu trả lời của mình. Nếu bạn nghĩ rằng tôi đang để lại một cái gì đó ra, xin vui lòng cho tôi biết trong một bình luận.


83
2017-08-20 03:50



Đây là IMO khá tốt đọc và một đóng góp có giá trị (đáp ứng chín năm sau khi câu hỏi đã được đặt ra có thể có một số mùi, nhưng không phải trong trường hợp này ít nhất là cho tôi). Cảm ơn Aaron. - Dilettant
@Dilettant Smells là các quy tắc của ngón tay cái hoặc phỏng đoán khiến chúng ta nhìn kỹ hơn. Một số người dùng mới đăng câu trả lời trễ về cơ bản sao chép các câu trả lời khác và đó là thứ mà chúng tôi lo ngại khi nói đến câu trả lời muộn. Câu trả lời muộn làm tăng giá trị là khá hoan nghênh, tuy nhiên - nếu không chúng tôi sẽ đóng các bài đăng sau một khoảng thời gian, như Reddit. - Aaron Hall♦


Câu trả lời của Patrick (được chấp nhận) đúng: if not a: là đúng cách để làm điều đó. Câu trả lời của Harley Holcombe đúng là điều này nằm trong hướng dẫn về phong cách PEP 8. Nhưng những gì không có câu trả lời giải thích là lý do tại sao nó là một ý tưởng tốt để làm theo các thành ngữ-ngay cả khi bạn cá nhân tìm thấy nó không đủ rõ ràng hoặc gây nhầm lẫn cho người dùng Ruby hoặc bất cứ điều gì.

Mã Python, và cộng đồng Python, có thành ngữ rất mạnh. Theo các thành ngữ đó, mã của bạn dễ đọc hơn cho bất kỳ ai có kinh nghiệm bằng Python. Và khi bạn vi phạm những thành ngữ đó, đó là một tín hiệu mạnh mẽ.

Đó là sự thật mà if not a: không phân biệt danh sách trống từ None, hoặc số 0 hoặc các bộ trống hoặc các loại bộ sưu tập do người dùng tạo hoặc các loại không được tạo hoàn toàn do người dùng tạo hoặc mảng NumPy đơn lẻ đóng vai trò vô hướng với các giá trị falsey, v.v ... Và đôi khi điều quan trọng là rõ ràng về điều đó. Và trong trường hợp đó, bạn biết  bạn muốn rõ ràng, vì vậy bạn có thể kiểm tra chính xác điều đó. Ví dụ, if not a and a is not None:có nghĩa là "bất cứ điều gì falsey trừ Không", trong khi if len(a) != 0: có nghĩa là "chỉ các chuỗi rỗng - và bất kỳ thứ gì ngoài chuỗi là một lỗi ở đây", v.v. Bên cạnh thử nghiệm cho chính xác những gì bạn muốn kiểm tra, điều này cũng báo hiệu cho người đọc rằng thử nghiệm này là quan trọng.

Nhưng khi bạn không có bất cứ điều gì để được rõ ràng về, bất cứ điều gì khác hơn if not a: là gây hiểu nhầm cho người đọc. Bạn đang báo hiệu một cái gì đó quan trọng khi nó không phải là. (Bạn cũng có thể làm cho mã ít linh hoạt hơn, hoặc chậm hơn, hoặc bất cứ điều gì, nhưng đó là tất cả ít quan trọng hơn.) Và nếu bạn thường xuyên đánh lừa người đọc như thế này, sau đó khi bạn làm cần phải làm cho một sự khác biệt, nó sẽ vượt qua không được chú ý bởi vì bạn đã được "khóc sói" trên tất cả các mã của bạn.


82
2017-12-03 02:21





Tôi đã thấy bên dưới được ưu tiên:

if not a:
    print("The list is empty or null")

63
2017-09-10 06:28



None không phải là một danh sách; nó là kiểu riêng của nó. - Yann Vernier


Tại sao chọn tất cả?

Không ai có vẻ đã giải quyết vấn đề của bạn nhu cầu để kiểm tra danh sách ở nơi đầu tiên. Vì bạn không cung cấp ngữ cảnh bổ sung, tôi có thể tưởng tượng rằng bạn có thể không cần phải thực hiện việc kiểm tra này ngay từ đầu, nhưng không quen thuộc với việc xử lý danh sách bằng Python.

Tôi cho rằng hầu hết các pythonic cách không phải là kiểm tra ở tất cả, mà là để chỉ xử lý danh sách. Bằng cách đó, nó sẽ làm điều đúng cho dù trống rỗng hay đầy đủ.

a = []

for item in a:
    <do something with item>

<rest of code>

Điều này có lợi ích của việc xử lý bất kỳ nội dung nào của một, trong khi không yêu cầu kiểm tra cụ thể cho sự trống rỗng. Nếu một trống, khối phụ thuộc sẽ không thực hiện và thông dịch viên sẽ rơi vào dòng tiếp theo.

Nếu bạn thực sự cần kiểm tra mảng trống, các câu trả lời khác là đủ.


53
2017-10-06 19:25



Vấn đề là, hãy kiểm tra xem danh sách có trống không là khá quan trọng, ít nhất là đối với tôi. Bạn đã xem xét liệu có một số kịch bản bên trong <rest of code> có thể sử dụng kết quả từ for vòng lặp? Hoặc trực tiếp sử dụng một số giá trị trong a? Thật vậy, nếu kịch bản được thiết kế để chạy với đầu vào được kiểm soát chặt chẽ, kiểm tra có thể là một chút không cần thiết. Nhưng trong hầu hết các trường hợp, đầu vào khác nhau, và có một kiểm tra thường là tốt hơn. - Amarth Gûl
Đây là một điểm tốt trong hầu hết các trường hợp - jamylak
Trân trọng, không. Những gì tôi coi là một người không biết đủ về Python để biết rằng "nếu <list>:" là câu trả lời đúng, hỏi làm thế nào để kiểm tra một danh sách trống. Sau đó, tôi nhận thấy rất nhiều câu trả lời mà cung cấp các ý kiến ​​khác nhau, nhưng không ai dường như giải quyết nhu cầu ban đầu. Đó là những gì tôi đã cố gắng làm với câu trả lời của tôi - để họ kiểm tra sự cần thiết trước khi tiếp tục. Tôi tin rằng tôi đã gợi ý nhiều câu trả lời của tôi, rõ ràng. - MrWonderful
@ AmarthGûl - Làm thế nào có thể một được kết quả từ vòng lặp for tới tập lệnh bên trong <phần còn lại của mã> sẽ được xử lý? Trong một danh sách, có lẽ? Hoặc có thể là một dict? Nếu vậy, cùng một logic sẽ được áp dụng. Tôi không hiểu cách đầu vào biến có thể có bất kỳ hiệu ứng nào trong bất kỳ loại mã được thiết kế hợp lý nào, khi xử lý một danh sách trống sẽ là một ý tưởng tồi. - MrWonderful


len() là một hoạt động O (1) cho danh sách Python, chuỗi, dicts và bộ. Python trong nội bộ theo dõi số lượng các phần tử trong các thùng chứa này.

JavaScript có khái niệm tương tự về sự thật / hư hỏng.


45
2017-09-15 05:50





Tôi đã viết:

if isinstance(a, (list, some, other, types, i, accept)) and not a:
    do_stuff

đã được bình chọn -1. Tôi không chắc liệu đó có phải là do độc giả phản đối chiến lược hay nghĩ rằng câu trả lời không hữu ích như đã trình bày. Tôi sẽ giả vờ nó là thứ hai, vì --- bất cứ thứ gì được tính là "pythonic" --- đây là chiến lược chính xác. Trừ khi bạn đã loại trừ hoặc sẵn sàng xử lý các trường hợp a là, ví dụ, False, bạn cần một bài kiểm tra hạn chế hơn là chỉ if not a:. Bạn có thể sử dụng một cái gì đó như thế này:

if isinstance(a, numpy.ndarray) and not a.size:
    do_stuff
elif isinstance(a, collections.Sized) and not a:
    do_stuff

thử nghiệm đầu tiên là để đáp ứng với câu trả lời của @ Mike, ở trên. Dòng thứ ba cũng có thể được thay thế bằng:

elif isinstance(a, (list, tuple)) and not a:

nếu bạn chỉ muốn chấp nhận các trường hợp của các loại cụ thể (và các kiểu con của chúng), hoặc với:

elif isinstance(a, (list, tuple)) and not len(a):

Bạn có thể lấy đi mà không cần kiểm tra kiểu rõ ràng, nhưng chỉ khi bối cảnh xung quanh đã đảm bảo với bạn rằng a là giá trị của các loại bạn đã chuẩn bị để xử lý hoặc nếu bạn chắc chắn rằng các loại bạn không chuẩn bị xử lý sẽ làm tăng lỗi (ví dụ: TypeError nếu bạn gọi len trên một giá trị mà nó không được xác định) mà bạn đã sẵn sàng để xử lý. Nói chung, các công ước "pythonic" dường như đi theo cách cuối cùng này. Bóp nó như một con vịt và để nó nâng DuckError nếu nó không biết cách quack. Bạn vẫn phải suy nghĩ về những giả định kiểu mà bạn đang thực hiện, và liệu các trường hợp bạn chưa chuẩn bị để xử lý đúng có thực sự xảy ra lỗi ở đúng nơi không. Các mảng Numpy là một ví dụ tốt khi chỉ dựa vào một cách mù quáng len hoặc boolean typecast có thể không làm chính xác những gì bạn đang mong đợi.


29
2018-05-31 14:35



Rất hiếm khi bạn sẽ có một danh sách đầy đủ gồm 6 loại mà bạn muốn chấp nhận và không linh hoạt cho bất kỳ loại nào khác. Khi bạn cần loại điều đó, bạn có thể muốn có một ABC. Trong trường hợp này, nó có lẽ sẽ là một trong những ABC stdlib, như collections.abc.Sized hoặc là collections.abc.Sequence, nhưng nó có thể là một trong những bạn tự viết và register(list) trên. Nếu bạn thực sự có mã, điều quan trọng là phân biệt rỗng với falsey khác, và cũng để phân biệt danh sách và bộ dữ liệu từ bất kỳ chuỗi nào khác, thì điều này là đúng — nhưng tôi không tin bạn có mã như vậy. - abarnert
Lý do mọi người không thích điều này là bởi vì nó hoàn toàn unnessesary trong hầu hết các trường hợp. Python là một ngôn ngữ có kiểu con vịt, và mức mã hóa phòng thủ này chủ động cản trở điều đó. Ý tưởng đằng sau hệ thống kiểu Python là mọi thứ sẽ hoạt động miễn là đối tượng được truyền trong các hàm theo cách nó cần. Bằng cách thực hiện kiểm tra kiểu rõ ràng, bạn đang buộc người gọi sử dụng các loại cụ thể, chống lại chính hạt của ngôn ngữ đó. Mặc dù đôi khi những thứ như vậy là cần thiết (không bao gồm chuỗi bị xử lý như chuỗi), các trường hợp như vậy hiếm và hầu như luôn là danh sách đen tốt nhất. - Gareth Latty
Nếu bạn thực sự muốn kiểm tra xem giá trị có chính xác không [] và không phải thứ gì đó giả mạo thuộc loại khác, thì chắc chắn if a == []: được gọi là, thay vì mucking về với isinstance. - RemcoGerlich
Có một số áp lực tự động cho == Tuy nhiên. Trên đỉnh đầu của tôi, tôi không thể xác định được []. [] == () ví dụ trả về False. Nhưng ví dụ frozenset()==set() trả về True. Vì vậy, nó có giá trị ít nhất là đưa ra một số suy nghĩ cho dù một số loại không mong muốn có thể bị ép buộc để [] (hoặc ngược lại) khi làm a == []. - dubiousjim