2013-10-14 2 views
1
def get_max(r, a, b): 
    """ Returns the maximum value in the form (index, value). """ 
    return max([(x+a, r[a:b][x]) for x in xrange(len(r[a:b]))], key=lambda x:x[1]) 

Может ли кто-нибудь объяснить, что понимает этот список?Можете ли вы объяснить это понимание Python?

+3

Это хороший пример того, почему отсчеты читаемости при кодировании. – iCodez

+3

Это означает, что тот, кто написал этот код, не знал о 'перечислении' и не понимал' for' циклы. – abarnert

+0

'max (enumerate (my_list [start: end], start), key = itemgetter (1))' будет делать то же самое и более ясно для меня ... не знаю, почему эта функция существует даже –

ответ

6

Для эффективности это хорошая идея, чтобы избежать повторения ломтик r снова и

chunk = r[a:b] 
[(x+a, chunk[x]) for x in xrange(len(chunk))] 

Я думаю, что это также делает смысл кода немного яснее (это не совсем Pythonic) еще

chunk = r[a:b] 
[(i, j) for i, j in enumerate(chunk, a)] 

О, это прейскурантной идентичность постижение

list(enumerate(chunk, a)) 

так вместо того, чтобы все, что вафля, вы можете сказать

def get_max(r, a, b): 
    """ Returns the maximum value in the form (index, value). """ 
    return max(enumerate(r[a:b], a), key=lambda x:x[1]) 

, как @vonPetrushev пытается объяснить в комментариях, вы можете заменить функцию лямбда с itemgetter.

from operator import itemgetter 
def get_max(r, a, b): 
    """ Returns the maximum value in the form (index, value). """ 
    return max(enumerate(r[a:b], a), key=itemgetter(1)) 

Существует не так много разницы в производительности и версия itemgetter более описательная (до тех пор, как вы знаете, что делает itemgetter)

+0

Отлично! Я бы также рекомендовал использовать «itemgetter» - хотя это означало бы импорт из «оператора», он прояснит появление лямбда, а также мы можем четко определить ключевую функцию вне 'get_max': ' от оператора import itemgetter key1 = itemgetter (1) def get_max (r, a, b): return max (enumerate (r [a: b], a), key = key1) ' – vonPetrushev

+0

Спасибо большое! Отличное объяснение – user1985339

1

Давайте разложим его на части.

Во-первых, вот только listcomp по себе:

[(x+a, r[a:b][x]) for x in xrange(len(r[a:b]))] 

Это эквивалентно этой петле:

result=[] 
for x in xrange(len(r[a:b])): 
    result.append((x+a, r[a:b][x])) 

Итак, что же каждая часть делать?

r[a:b] - это подпоследовательность r от индекса a (включительно) до b (исключительно). Итак, len(r[a:b]) - это почти причудливый способ сказать b-a, но не совсем, потому что b может пройти мимо конца последовательности, или любой из индексов может быть отрицательным индексом. И xrange(len(r[a:b])) - это всего лишь цифры от 0 до этой длины (опять же эксклюзивные).

Теперь для каждого из этих чисел x от 0 до этой длины мы создаем кортеж (x+a, r[a:b][x]).

Давайте работать на примере:

>>> r = ['a', 'b', 'c', 'd', 'e', 'f'] 
>>> a = 2 
>>> b = 4 
>>> r[a:b] 
['c', 'd'] 
>>> len(r[a:b]) 
2 
>>> list(xrange(len(r[a:b]))) 
[0, 1] 
>>> x=0 
>>> (x+a, r[a:b][x]) 
(2, 'c') 
>>> x = 1 
>>> (x+a, r[a:b][x]) 
(3, 'd') 

Итак, как вы можете видеть, это создание списка (индекс, значение) для индексов от a к b, как это:

[(2, 'c'), (3, 'd')] 

гораздо лучше способ написать то же самое, это:

>>> list(enumerate(r))[a:b] 
[(2, 'c'), (3, 'd')] 

... или ...

>>> list(enumerate(r[a:b], a) 
[(2, 'c'), (3, 'd')] 
+0

Замечательно, что исходный код работает для таких вещей, как '(r, 1, -1)', он возвращает неверный индекс, если у вас есть отрицательный 'a' (например,' (r, -8, - 3) '). – nneonneo

1

r представляет собой последовательность, a является начальным индексом и b является показателем концовки. Пояснение списка даст список (index, r[index]) кортежей, где a <= index < b. Затем вызов max() возвращает кортеж с наибольшим значением (второй элемент в кортеже).

+1

Собственно, если кто-то переходит в '(r, 1, -1)', то ваша упрощенная версия не работает. – nneonneo

+0

Плюс, это все еще довольно трудно прочитать. Нет причин избегать вызова 'enumerate' ... – abarnert

+0

Хорошая точка, удаленная альтернативная версия, поэтому ответ теперь просто объяснение. Другие ответы, которые используют 'enumerate', хорошо подходят для покрытия. –

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