2009-03-15 16 views
10

Tôi thấy hình thức này mà đôi khi:Trường hợp sử dụng cho lồng ghép/nhiều danh sách hiểu hoặc biểu thức trình tạo. Khi nào nó thanh lịch hơn?

(k for k in (j for j in (i for i in xrange(10)))) 

Bây giờ điều này thực sự cúi não của tôi, và tôi thà nó đã không được trình bày theo cách này.

Có bất kỳ trường hợp sử dụng hoặc ví dụ nào về việc sử dụng các biểu thức lồng nhau này ở đó nó thanh lịch hơn và dễ đọc hơn nếu nó là một vòng lặp lồng nhau không?

Chỉnh sửa: Cảm ơn các ví dụ về cách đơn giản hóa việc này. Nó không thực sự là những gì tôi yêu cầu, tôi đã tự hỏi nếu có bất kỳ thời gian khi nó được thanh lịch.

+1

"Đôi khi"? Có thật không? Bạn đang đọc gì –

+1

Đoạn mã, dự án mã nguồn mở. Điều đó sẽ nhận được mã xem xét lại từ bất cứ điều gì tôi đã từng quản lý. –

+0

Bạn đã thấy một thứ như vậy ở đâu? Bạn có thể cung cấp một URL cụ thể không? –

Trả lời

18

Kiểm tra PEP 202 là nơi cú pháp hiểu danh sách được đưa vào ngôn ngữ.

Đối với sự hiểu biết ví dụ của bạn, có một quy tắc đơn giản từ Guido mình:

  • Hình thức [... cho x ... cho y ...] tổ, với chỉ số cuối cùng thay đổi nhanh nhất , giống như lồng nhau cho các vòng lặp.

Cũng từ PEP 202, phục vụ để trả lời câu hỏi của bạn:

 
Rationale 
    List comprehensions provide a more concise way to create lists in 
    situations where map() and filter() and/or nested loops would 
    currently be used. 

Nếu bạn đã có một tình huống như vậy, bạn có thể tìm thấy nó để được thanh lịch hơn. IMHO, mặc dù, nhiều danh sách lồng nhau có thể ít rõ ràng hơn trong mã của bạn hơn so với lồng nhau cho các vòng, vì các vòng lặp for dễ dàng được phân tích cú pháp một cách trực quan.

4

Vì chúng là biểu thức trình tạo, bạn có thể liên kết từng tên với tên riêng để làm cho nó dễ đọc hơn mà không có bất kỳ thay đổi nào về hiệu suất. Thay đổi nó thành một vòng lặp lồng nhau có thể sẽ gây bất lợi cho hiệu suất.

irange = (i for i in xrange(10)) 
jrange = (j for j in irange) 
krange = (k for k in jrange) 

Nó thực sự không quan trọng bạn chọn, tôi nghĩ rằng ví dụ nhiều dòng dễ đọc hơn, nói chung.

5

Trong trường hợp ví dụ của bạn, tôi có lẽ sẽ viết nó như:

foos = (i for i in xrange(10)) 
bars = (j for j in foos) 
bazs = (k for k in bars) 

Với tên mô tả nhiều hơn, tôi nghĩ rằng đây có lẽ sẽ là khá rõ ràng, và tôi không thể tưởng tượng có là bất kỳ hoạt động đo lường Sự khác biệt.

Có lẽ bạn đang nghĩ nhiều hơn các biểu thức như:

(x for x in xs for xs in ys for ys in lst) 

- trên thực tế, đó không phải là thậm chí còn hiệu lực. Bạn phải đặt mọi thứ theo thứ tự khác:

(x for ys in lst for xs in ys for x in xs) 

tôi có thể viết đó như là một cách nhanh chóng để làm phẳng một danh sách, nhưng nói chung tôi nghĩ rằng bạn đang ghi: thời gian giúp bạn tiết kiệm bằng cách gõ ít thường là cân bằng bởi thời gian thêm bạn chi tiêu nhận được biểu thức máy phát điện ngay.

12

Nếu bạn đang lo lắng về quá nhiều phức tạp trên một dòng, bạn có thể chia nó:

(k for k in 
    (j for j in 
     (i for i in xrange(10)))) 

Tôi luôn tìm thấy sự tiếp tục dòng để nhìn một chút lạ trong Python, nhưng điều này không làm cho nó dễ dàng hơn để xem những gì mỗi người lặp lại. Vì việc chuyển nhượng/tra cứu thêm sẽ không thực hiện hoặc phá vỡ bất cứ điều gì, bạn cũng có thể viết như thế này:

gen1 = (i for i in xrange(10)) 
gen2 = (j for j in gen1) 
gen3 = (k for k in gen2) 

Thực tế, tôi không nghĩ rằng tôi đã từng lồng ghép hiểu hơn 2-sâu , và vào thời điểm đó nó vẫn còn khá dễ hiểu.

+0

Tôi đã xóa các lần thoát. – Soviut

0

Khái niệm:

(k for k in (j for j in (i for i in xrange(10)))) 

tương đương với:

(i for i in xrange(10)) 

đó là gần như giống nhau:

xrange(10) 

Các biến thể cuối cùng là thanh lịch hơn so với cái đầu tiên.

0

tôi thấy nó có thể hữu ích và thanh lịch trong những tình huống như thế này, nơi bạn có mã như thế này:

output = [] 
for item in list: 
    if item >= 1: 
     new = item += 1 
     output.append(new) 

Bạn có thể làm cho nó một lớp lót như thế này:

output = [item += 1 for item in list if item >= 1] 
1

Nên biết trước: sang trọng là một phần một vấn đề của hương vị.

Việc hiểu danh sách không bao giờ nhiều hơn xóa so với mở rộng tương ứng cho vòng lặp. Đối với vòng lặp cũng có nhiều hơn mạnh mẽ so với việc hiểu danh sách. Vậy tại sao lại sử dụng chúng?

Tính năng hiểu danh sách là ngắn gọn - chúng cho phép bạn làm điều gì đó trong một dòng.

Thời gian sử dụng danh sách hiểu là khi bạn cần một danh sách nhất định, nó có thể được tạo trên bay khá dễ dàng và bạn không muốn hoặc cần các đối tượng trung gian treo xung quanh. Điều này có thể xảy ra khi bạn cần phải đóng gói một số đối tượng trong phạm vi hiện tại vào một đối tượng duy nhất mà bạn có thể đưa vào một chức năng, như dưới đây:

list1 = ['foo', 'bar'] 
list2 = ['-ness', '-ity'] 
return filterRealWords([str1+str2 for str1 in list1 for str2 in list2]) 

Mã này là về là có thể đọc hơn so với phiên bản mở rộng, nhưng nó là ngắn hơn nhiều. Nó tránh tạo/đặt tên một đối tượng chỉ được sử dụng một lần trong phạm vi hiện tại, được cho là thanh lịch hơn.

Các vấn đề liên quan