2013-05-07 2 views
9

Обычно я знаю, что мы можем сделать sum([func(x,x) for x in i]), но я получил проверку if и два для циклов, так что самый пифонический способ написать код ниже. вы можете предположить, что сходство вернет число независимо от того, какой тип вы его дадите. Вы также можете предположить, что он действительно получит только ints и chars.Python, лучший способ написать сумму из двух для циклов

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' не находится внутри какого-либо цикла, поэтому ... зачем он должен находиться внутри' sum'? – abarnert

+1

Для вашего примера вместо понимания списка 'sum ([func (x, y) для x в i])' вы можете использовать 'sum (func (x, y) для x в i)' как генератор и не генерировать промежуточный список – 2013-05-07 22:08:18

ответ

10

Может быть что-то вроде этого:

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

Или:

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

Или (в предположении, что строка, набор или какой-либо другой итерируемый тип по какой-либо причине не нарушает вашу функцию):

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

Если вы специально хотите проверить, если что-то итерация, вы можете сделать это следующим образом:

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

Если есть определенные Iterable типов вы не хотите, реагировать на те:

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

Нет причина использовать 'any' с' isinstance', когда вы можете просто передать все типы самому 'isinstance'. – abarnert

+0

ОК - спасибо. Хороший улов. Сделано редактирование – dawg

+1

Downvoter - Могу ли я спросить, почему? Я сделал предложенное редактирование. – dawg

5

Поскольку if не внутри цикла, он не должен быть в списке понимания, когда вы преобразовать его:

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

Между тем, вы действительно не нужен список понимание здесь, выражение генератор будет иметь тот же эффект, без необходимости создания списка:

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) 

Между тем, isinstance может принять tuple типов, чтобы проверить, так:

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

... но на самом деле, я не думаю, что вы хотите проверить в первую очередь. До тех пор, как a является любым итерабельным, код будет работать, поэтому ... почему я должен заставить его быть этими конкретными типами? Если вы не хотите исключение, просто обработать исключение:

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

@ DSM: Да, мой ответ уже говорит об этом. Но на самом деле он не должен использовать его вообще, как я объяснил в редакции. (Во всяком случае, это не относится к основному вопросу, который он задавал.) – abarnert

+0

В первой версии было предложение «Между тем,' isinstance' может использовать «кортеж» типов для проверки, но на самом деле, почему вы нужно вообще проверить? Я расширил первую часть в первом редактировании, а второй - во втором редактировании. – abarnert

+0

+1 для [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) 

да, типа не то же самое, как isistance, но это не драматический вопрос ..

, если бы OP захотел использовать этот фрагмент кода с чем-то похожим на dict, list или tuples (так что с подклассами и всеми), на самом деле нужно просто проверить, что a iserable.

что-то вроде:

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

с использованием 'type' это не то же самое, что 'isinstance', и не очень хорошая идея. – cmd

+1

Ну неважный вопрос, почему бы и нет? – EasilyBaffled

+0

@EasilyBaffled: Что, если я передам что-то, что является экземпляром подкласса 'dict'? Это будет работать с 'isinstance', но он не будет работать с явной проверкой' type'. – abarnert

9

Вы, вероятно, хотите что-то вроде:

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

Почему это было ниспровергнуто? Правда, он не добавляет ничего, что еще не было, по крайней мере, в двух ранее существовавших ответах, но с каких пор это причина для понижения? – abarnert

+0

Не знаю, что такое downvote, но «защищать» ответ: когда он был написан, ни один другой ответ не передал кортеж «isinstance», а также не показывал, что 'sum' по умолчанию 0, что делает безусловное присвоение ненужным. Кроме того, некоторые из существующих ответов были излишне многословными. – user4815162342

+0

Учитывая выбор объясняющих изменений, вряд ли ОП понимает, а также дает ему некоторый код, который, по-видимому, делает то, что он хочет по волшебству, поэтому он может грузить свой путь к коду, который он не может поддерживать или даже отлаживать, Думаю, что первый «слишком многословный». (Кроме того, мой ответ был первым. И, хотя он не _show_ использовал 'isinstance' с кортежем, он имел такую ​​же информацию:« Между тем, 'isinstance' может использовать' tuple' типов для проверки ... «Я не показывал это, потому что думал, что лучше показать, что он вообще не нуждался в проверке типов.) – abarnert

1

В одной строке;)

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

«[Показания читаемости] (http://www.python.org/dev/peps/pep-0020/)« – Johnsyweb

+1

Конечно ... Вот почему я положил смайлик туда;) – tamasgal

+1

ОП не просил ввести код в гольф. – abarnert

7

Вы могли бы использовать некоторые функции из itertools, возможно:

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

и, как другие отметили, возможно, также передать кортеж типов в isinstance(), если вам действительно нужно проверить.

+0

+1 для itertools-foo – user4815162342

Смежные вопросы