2009-12-15 32 views
6

Xét đoạn mã sau:lisp kiểu phong cách 'let` cú pháp trong Python danh sách-comprehensions

>>> colprint([ 
     (name, versions[name][0].summary or '') 
     for name in sorted(versions.keys()) 
    ]) 

gì mã này, không có gì để in các yếu tố của từ điển versions thứ tự tăng dần của keys của nó, nhưng kể từ khi value là một danh sách được sắp xếp khác, chỉ bản tóm tắt của thành phần đầu tiên ('tối đa') được in.

Kể từ khi tôi quen với let từ lisp, tôi viết lại trên như:

>>> colprint([ 
     (name, package.summary or '') 
     for name in sorted(versions.keys()) 
     for package in [versions[name][0]] 
    )] 

Bạn có nghĩ rằng điều này vi phạm being Pythonic? Nó có thể được cải thiện không?

Lưu ý: Đối với người tò mò, colprint được định nghĩa here.

+3

Heh. Cố gắng lispy là _always_ unpythonic. Python cố gắng không được lispy cứng như nó có thể. – Svante

+2

Thật khó để nói được Parsel với một lisp; [. – Tordek

+0

python không cố gắng không giống như lisp. Chính GvR đã nói rằng PYthon và Lisp rất giống nhau, và rằng sự khác biệt là hời hợt hơn. Tôi đến từ một kế hoạch trở lại mặt đất bản thân mình, nhưng tôi đã sử dụng python gần như độc quyền trong ba năm nay, và tôi thích cách thứ hai nhiều hơn lần đầu tiên. – Broseph

Trả lời

7

Tại sao không khai thác bộ dữ liệu?

colprint([(name, version[0].summary or '') 
     for (name, version) in sorted(versions.iteritems())]) 

hoặc, thậm chí

colprint(sorted([(name, version[0].summary or '') 
      for (name, version) in versions.iteritems()])) 

Ngoài ra, bạn có thể xem xét (trong ví dụ đầu tiên của tôi) loại bỏ các [] s, vì như vậy bạn sẽ có được một máy phát điện thay vì một danh sách (mà có thể hoặc có thể không có ích, vì tôi đoán điều này sẽ in toàn bộ mảng, vì vậy bạn sẽ không lưu bất kỳ đánh giá nào).

+0

Tôi sắp đề xuất cùng một kiểu dáng –

+0

Có vẻ tốt hơn; ngoại trừ tôi muốn sử dụng 'items()' thay vì 'iteritems()' vì nó không được chấp nhận trong Py3k (và 'colprint' chấp nhận một danh sách phẳng) –

4

Vì vậy, bạn đang sử dụng "for x in [y]" để thay thế cho "let x y".

Cố gắng mô phỏng cú pháp ngôn ngữ bằng ngôn ngữ khác không bao giờ là ý tưởng hay. Tôi nghĩ rằng phiên bản gốc là rõ ràng hơn nhiều.

0

Bạn có thể di chuyển sắp xếp đến cuối để tránh một số danh sách trung gian.

này trông đẹp hơn một chút tôi đoán:

colprint(sorted(
     (name, version[0].summary or '') 
     for (name,version) in versions.iteritems()) 
    )) 

Python3 có thể làm tốt hơn:

colprint(sorted(
     (name, first_version.summary or '') 
     for (name,(first_version,*_)) in versions.items()) 
    )) 
+1

? Ngôn ngữ này là gì? Tôi nhận được lỗi cú pháp trong Python. –

+2

Bài thứ 2 là Python ** 3 ** –

5

tôi sẽ không sử dụng "khó khăn cho khoản" (hay "let-tương đương") trong hầu hết các trường hợp, nhưng nếu tôi là cách tự nhiên để tránh sự lặp lại, đặc biệt là sự lặp lại tốn kém. Ví dụ.

xs = [(y, y*1.2, y-3.4) for z in zs for y in [somefun(z)] ] 

trông đẹp hơn nhiều đối với tôi vì gọi somefun ba lần -!) Vì vậy, nó có giá trị giữ trong tâm trí, thậm chí nếu có lẽ không giá trị sử dụng, nơi nó không loại bỏ sự lặp lại.

1

Như Tordek nói, bạn có thể sử dụng items() hoặc iteritems() trong trường hợp này để tránh vấn đề này:

colprint(sorted((name, packages[0].summary or '') 
       for (name, packages) in versions.items())) 

Di chuyển sắp xếp bên ngoài là một liên lạc tốt đẹp.

[Lưu ý rằng việc sử dụng items() đã thay đổi thứ tự sắp xếp một chút - nó được sử dụng theo tên với các mối quan hệ được giải quyết theo thứ tự ban đầu (sắp xếp bằng Python ổn định), giờ là theo tên với các mối quan hệ được giải quyết bằng tóm tắt.Vì thứ tự ban đầu của một dict là ngẫu nhiên, hành vi mới có lẽ tốt hơn.]

Nhưng đối với các ứng dụng khác (ví dụ như ví dụ của Alex Martelli), "cho" giống nhau có thể hữu ích. Tôi cũng đã từng phát hiện ra thủ thuật for var in [value], nhưng bây giờ tôi thấy nó xấu xí. Một sạch thay thế có thể là một "đường ống" của comprehensions/máy phát điện, sử dụng "trang trí/undecorate" lừa để vượt qua giá trị gia tăng trong một tuple:

# You could write this with keys() or items() - 
# I'm just trying to examplify the pipeline technique. 
names_packages = ((name, versions[name][0]) 
        for name in versions.keys()) 

names_summaries = ((name, package.summary or '') 
        for (name, package) in names_packages) 

colprint(sorted(names_summaries)) 

Hoặc áp dụng cho ví dụ Alex:

ys = (somefun(z) for z in zs) 
xs = [(y, y*1.2, y-3.4) for y in ys] 

(trong đó bạn thậm chí không cần z giá trị ban đầu, vì vậy các giá trị trung gian không phải là tuples.)

Xem http://www.dabeaz.com/generators/ ví dụ mạnh mẽ hơn của kỹ thuật "đường ống" ...

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