2017-02-06 13 views
3

Обычно мы должны (1) объявить список (2) вычислить сумму этого списка с помощью sum()Python: как вычислить сумму списка, не создавая сначала весь список?

Но теперь я хочу, чтобы указать список начинается с 1 и интервалом 4, 100 элементов, как это:

[1,5,9,13,17,21,25,29,33,37,…] 

Я не хочу envolve математической формулы, так

(1) Как получить сумму, даже не объявляя этот список?

(2) Как быстро получить сумму от 101-го элемента до 200-го элемента этого списка?

ответ

2

Просто используйте itertools.count чтобы получить счетчик и itertools.islice, чтобы получить необходимое количество элементов (вы можете оценить эти случаи, но они не создают список):

>>> from itertools import count, islice 
>>> sum(islice(count(1, step=4), 100)) # get the first 100 elements and sum them 
19900 

islice также поддерживает старт/стоп:

>>> sum(islice(count(1, step=4), 101, 200)) # 101st element to 200th 
59499 
1

Вы можете использовать генераторы с sum, чтобы избежать создания списка на первом:

result = sum(x for x in range(1, 401, 4)) 

Как @Mad Физик упоминался в комментариях, вам не нужно даже в x for x части:

result = sum(range(1, 401, 4)) 
+3

Это не список понимания и передачи в диапазоне само по себе хорошо. –

+0

Нет проблем. См. Комментарий, который я сделал для другого ответа. 'x for x in ...' почти никогда не требуется. –

+0

Это технически называется выражением генератора, а не пониманием: http://stackoverflow.com/documentation/python/292/generators#t=201609020956268959493 –

2

Встроенный класс range делает именно то, что вы хотите в Python 3. В Python 2 используйте xrange. вместо. Например:

for i in range(1, 401, 4): ... 

range Объект не содержит полный список. Он записывает только размер начала, конца и шага. Итератор также записывает текущую позицию.

Важно использовать xrange в Python 2, потому что функция диапазона вернет весь список, который точно противоположный тому, что вы хотите.

a = range(1, 401, 4) 
sum(a) 

рассчитает сумму, которую вы хотите, и позволяет повторно использовать a впоследствии.

Замечание о количестве 401

Конец диапазона является исключительным. Существует несколько общих формул для получения правильного количества элементов в диапазоне. start + count * step - это тот, который я выбрал здесь, потому что он самый простой. Это также самое большое число, которое даст count, а не count + 1 элементов в диапазоне. start + (count - 1) * step + 1 - это формула для наименьшего числа, которая даст вам count элементов. Поскольку вам нужно 100 элементов, конечное значение 398, 399 или 400 даст вам тот же результат, что и 401.

+2

Это не совсем точный для описания объекта «range» Python 3 как генератора. Это объект последовательности, а не итератор. Помимо повторного использования, вы можете делать такие вещи, как 'len (range (...))' и 'range (...) [index_or_slice]', и он работает. Это невозможно с генераторами. – Blckknght

+0

@Blckknght. Это абсолютно так, если генератор определяет соответствующие методы. Но вы правы, диапазон не является генератором, так как вы не можете позвонить дальше. –

+0

Вы не можете определить методы для объекта-генератора. Вы создаете его, вызывая функцию генератора (функцию с выражениями 'yield' в нем) или используя выражение генератора. Вы можете написать свой собственный класс итератора, но это не то же самое, что генератор. И если вы хотите использовать методы '__len__' и' __getitem__', вы, вероятно, хотите, чтобы ваш тип был последовательностью (например, 'range' is) и не был итератором. – Blckknght

1

Вы можете написать генератор:

def ir(start=1, end=400, step=4): 
    while True: 
     yield start 
     start+=step 
     if start>=end: break 

Или, если вы хотите определенное количество элементов:

def ir(start=1, n=100, step=4): 
    cnt=0 
    while True: 
     yield start 
     cnt+=1 
     start+=step 
     if cnt>=n: break 

А потом просуммировать, что:

>>> sum(ir()) 
19900 
+0

Зачем изобретать колесо? –

+0

Потому что вы можете включить гораздо больше в пользовательскую функцию, например, пропустить 20-е или пропустить [Грегорианский календарь] (https://en.wikipedia.org/wiki/Leap_year) – dawg