2013-05-07 14 views
9

Thông thường tôi biết chúng ta có thể làm sum([func(x,x) for x in i]), nhưng tôi có một nếu kiểm tra và hai cho vòng, vì vậy cách pythonic nhất để viết mã dưới đây là những gì. bạn có thể giả định rằng sự giống nhau sẽ trả về một số bất kể bạn cung cấp loại nào. Bạn cũng có thể giả định rằng nó sẽ thực sự chỉ nhận được int và ký tự.Python, cách tốt nhất để viết tổng của hai cho vòng

x = 0 
if isinstance(a, dict) or isinstance(a, list) or isinstance(a, tuple): 
    for i in a: 
     for j in b: 
      x += similarity (i,j) 
+5

'if' không nằm trong vòng lặp nào, vì vậy… tại sao cần phải nằm trong' tổng hợp'? – abarnert

+1

Ví dụ của bạn, thay vì danh sách hiểu 'sum ([func (x, y) cho x trong i])' bạn có thể sử dụng 'sum (func (x, y) cho x trong i)' làm trình tạo và không tạo danh sách trung gian –

Trả lời

10

Có lẽ một cái gì đó như thế này:

x=0 
if isinstance(a,(dict,list,tuple)): 
    x=sum(similarity(i,j) for i in a for j in b) 

Hoặc:

x=(sum(similarity(i,j) for i in a for j in b) if isinstance(a,(dict,list,tuple)) 
    else 0) 

Hoặc (giả định rằng một chuỗi, thiết lập hoặc một số loại có thể lặp lại khác không phá vỡ chức năng của bạn vì một số lý do):

try: 
    x=sum(similarity(i,j) for i in a for j in b) 
except TypeError: 
    x=0 

Nếu bạn đang tìm cách cụ thể để kiểm tra nếu có điều gì là iterable, bạn có thể làm điều đó theo cách này:

from collections import Iterable 
if isinstance(e, Iterable): 
    ... 

Nếu có một số loại iterable bạn không muốn, phản ứng với những:

if isinstance(e, Iterable) and not isinstance(el, str): 
    # an iterable that is not a string... 
+5

Không có lý do để sử dụng 'any' với' isinstance', khi bạn có thể chuyển tất cả các kiểu thành 'isinstance'. – abarnert

+0

OK - cảm ơn. Nắm bắt tốt. Chỉnh sửa được thực hiện – dawg

+1

Downvoter - Tôi có thể hỏi tại sao không? Tôi đã thực hiện chỉnh sửa được đề xuất .. – dawg

5

Kể từ khi if không phải là bên trong một vòng lặp, nó không cần phải được bên trong danh sách hiểu khi bạn chuyển đổi nó:

x = 0 
if isinstance(a, dict) or isinstance(a, list) or isinstance(a, tuple): 
    x = sum([similarity(i, j) for i in a for j in b]) 

Trong khi đó, bạn thực sự không cần một danh sách hiểu ở đây, một biểu thức máy phát điện sẽ có tác dụng tương tự mà không cần phải xây dựng một danh sách:

x = 0 
if isinstance(a, dict) or isinstance(a, list) or isinstance(a, tuple): 
    x = sum(similarity(i, j) for i in a for j in b) 

Trong khi đó, isinstance có thể mất một tuple các loại để kiểm tra, vì vậy:

x = 0 
if isinstance(a, (dict, list, tuple)): 
    x = sum(similarity(i, j) for i in a for j in b) 

... nhưng thực sự, tôi không nghĩ rằng bạn muốn kiểm tra ở nơi đầu tiên. Miễn là a là bất kỳ lần lặp nào, mã sẽ hoạt động, vì vậy… tại sao tôi nên ép nó là các loại cụ thể? Nếu bạn không muốn một ngoại lệ, chỉ cần xử lý các ngoại lệ:

try: 
    x = sum(similarity(i, j) for i in a for j in b)) 
except TypeError: 
    x = 0 
+0

@ DSM: Có, câu trả lời của tôi đã nói điều đó. Nhưng thực sự, anh ấy không nên sử dụng nó chút nào, như tôi đã giải thích trong bản chỉnh sửa. (Bất kỳ giá nào, nó không liên quan đến câu hỏi chính mà anh ta đang hỏi.) – abarnert

+0

Phiên bản đầu tiên có câu "Trong khi đó,' isinstance' có thể lấy một 'tuple' loại để kiểm tra, nhưng thực sự, tại sao bạn cần phải kiểm tra ở tất cả? " Tôi đã mở rộng phần đầu tiên trong bản chỉnh sửa đầu tiên và vào phần thứ hai trong bản chỉnh sửa thứ hai. – abarnert

+0

+1 cho thành phần [EAFP] (http://docs.python.org/2/glossary.html#term-eafp). – Johnsyweb

0
if type(a) in [dict, list, tuple]: 
    x += sum(similarity(i, j) for i in a for j in b) 

yeah, loại không giống như isistance nhưng nó không phải là một vấn đề đáng kể ..

nếu OP muốn sử dụng đoạn mã đó với bất kỳ thứ gì giống như dict, list hoặc tuples (vì vậy với các lớp con và tất cả) nó thực sự chỉ cần kiểm tra xem a có thể lặp lại hay không.

cái gì đó như:

def isiterable(obj): 
    try: 
     iter(obj) 
     return True 
    except TypeError: 
     return False 

if isiterable(a): 
    x += sum(similarity(i, j) for i in a for j in b) 
+7

bằng 'type' không giống như 'isinstance', và không phải là ý tưởng hay – cmd

+1

Câu hỏi ngớ ngẩn, tại sao không? – EasilyBaffled

+0

@EasilyBaffled: Nếu tôi chuyển vào một thứ gì đó là một thể hiện của một phân lớp của 'dict'? Điều đó sẽ làm việc với 'isinstance', nhưng nó sẽ không hoạt động với việc kiểm tra rõ ràng' type'. – abarnert

9

Bạn có thể muốn một cái gì đó như:

if isinstance(a, (dict, list, tuple)): 
    x = sum(similarity(i, j) for i in a for j in b) 
else: 
    x = 0 
+1

Tại sao điều này lại được giảm giá? Đúng, nó không thêm bất kỳ thứ gì chưa có trong ít nhất 2 câu trả lời đã tồn tại từ trước, nhưng vì khi nào thì đó là lý do để downvote? – abarnert

+0

Không có ý kiến ​​về downvote, nhưng để "bảo vệ" câu trả lời: khi nó được viết, không có câu trả lời nào khác chuyển một tuple tới 'isinstance', cũng không hiển thị' sum' mặc định là 0, làm cho việc gán vô điều kiện không cần thiết. Ngoài ra, một số câu trả lời hiện có là không cần thiết dài dòng. – user4815162342

+0

Với lựa chọn giải thích những thay đổi mà OP không thể hiểu được, so với đưa cho anh ta một số mã mà anh ta muốn bằng ma thuật để anh ta có thể vận chuyển hàng hóa để mã anh ấy không thể duy trì hoặc thậm chí gỡ lỗi, tôi don ' t nghĩ rằng trước đây là "quá dài dòng". (Ngoài ra, câu trả lời của tôi là câu đầu tiên. Và, trong khi nó không _show_ bằng cách sử dụng 'isinstance' với một tuple, nó có cùng thông tin:" Trong khi đó, 'isinstance' có thể lấy một' tuple' các loại để kiểm tra ... "Tôi không thể hiện điều đó vì tôi nghĩ tốt hơn nên chứng minh rằng anh ấy không cần kiểm tra kiểu." – abarnert

1

Trong một dòng;)

x = sum(similarity(i, j) for i in a for j in b) if isinstance(a, (dict, list, tuple)) else 0 
+5

"[Số khả năng đọc] (http://www.python.org/dev/peps/pep-0020/)" – Johnsyweb

+1

Tất nhiên ... Đó là lý do tại sao tôi đặt biểu tượng mặt cười trong đó;) – tamasgal

+1

OP không yêu cầu chơi gôn mã. – abarnert

7

Bạn có thể sử dụng một số chức năng từ itertools, có lẽ:

from itertools import starmap, product 
x = sum(starmap(similarity, product(a, b))) 

và như những người khác chú ý, cũng có thể vượt qua một tuple các loại để isinstance() nếu bạn thực sự cần phải kiểm tra.

+0

+1 cho itertools-foo – user4815162342