Для петель (новичок)

Я недавно начал изучать Python, и концепция циклов for все еще немного сбивает меня с толку. Я понимаю, что это вообще следует форматуfor x in y, гдеy это просто какой-то список.

Цикл для каждогоfor (int n: someArray) становитсяfor n in someArray,

И для циклаfor (i = 0; i < 9; i-=2) может быть представленfor i in range(0, 9, -2)

Предположим, вместо постоянного приращения, я хотелi*=2, или дажеi*=i, Это возможно, или я должен был бы использовать цикл while вместо этого?

 dwerner04 мая 2012 г., 01:17
Более точно, range () не может предоставить массив с отрицательным шагом для положительного значения. Это бесконечный цикл.
 Antti Haapala27 мая 2016 г., 08:08
Последнийfor цикл не имеет правильного конечного условия, еслиi являетсяint а это C. В любом случае, это не тот диапазон, который вы сказали.
 Ashwini Chaudhary04 мая 2012 г., 01:32
@ user1320925 вы хотите, чтобы это были значения i: 1 2, 4, 8, 16, 32 ....
 hexparrot04 мая 2012 г., 01:05
вашfor i in range(0,9,-2) не будет повторяться в обратном направлении, если первое число меньше второго.

Ответы на вопрос(5)

что часть «списка» Python может быть любой повторяемой последовательностью.

Примеры

Строка

for c in 'abcdefg':
   # deal with the string on a character by character basis...

Файл

with open('somefile','r') as f:
    for line in f:
         # deal with the file line by line

Словарь

d={1:'one',2:'two',3:'three'}
for key, value in d.items():
   # deal with the key:value pairs from a dict

Кусочек списка:

l=range(100)
for e in l[10:20:2]:
    # ever other element between 10 and 20 in l 

и т. д. и т. д. и т. д.

Так что это на самом деле намного глубже, чем «просто список»

Как уже говорили другие, просто установите итеративное значение таким, каким вы хотите, чтобы оно было для ваших примеров:

 for e in (i*i for i in range(10)):
     # the squares of the sequence 0-9...

 l=[1,5,10,15]
 for i in (i*2 for i in l):
     # the list l as a sequence * 2...
 user68863504 мая 2012 г., 01:35
@ Tom Wijsman: ОП заявляетthe concept of for loops is still a little confusing for me. I understand that it generally follows the format for x in y, where y is just some list. Я уточнил, что у тебя гораздо больше, чем просто список
 Tom Wijsman04 мая 2012 г., 01:39
Это было непонятно из твоего ответа, спасибо.
 Gareth Latty04 мая 2012 г., 01:23
+ 1 - Это хороший момент. Для циклов перебирайте любые итерируемые, а не только списки.
 Tom Wijsman04 мая 2012 г., 01:33
Я не понимаю, как это отвечает на вопрос.

forикл @ перебирает элементы списка. Список может содержать все что угодно, поэтому вы можете заранее составить список, содержащий каждый шаг.

A for цикл также может перебирать"генератор", который представляет собой небольшой фрагмент кода вместо фактического списка. В Python,range() на самом деле является генератором (хотя в Python 2.x,range() вернул список, покаxrange() был генератором).

Например

def doubler(x):
    while True:
        yield x
        x *= 2

for i in doubler(1):
    print i

Надfor цикл напечатает

1
2
4
8

и так далее, пока не нажмешь Ctrl + C.

 Gareth Latty04 мая 2012 г., 01:23
Готово, +1 к твоему - хороший ответ, можно творить чудеса с генераторами.
 Gareth Latty04 мая 2012 г., 01:08
Я бы сказал, что автономный генератор излишне для этого - выражение генератора, вероятно, сделает то же самое. Например:for i in (x*2 for x in range(10)):
 Gareth Latty04 мая 2012 г., 01:10
Хотя приятно знать, что ты можешь делать с этим больше, нехорошо советовать людям усложнять вещи. Вероятно, было бы неплохо также объяснить синтаксис выражений генератора, чтобы не допустить, чтобы спрашивающий сделал очень простые генераторы в виде полных функций.
 Greg Hewgill04 мая 2012 г., 01:11
Я рекомендую добавить ответ, демонстрирующий синтаксис выражения генератора.
 Greg Hewgill04 мая 2012 г., 01:09
Да, вы можете написать код более компактно. Тем не менее, я думаю, что полезно показать вкус того, что может сделать обобщенный генерато

Вы можете использоватьgenerator выражение сделать это эффективно и с небольшим лишним кодом:

for i in (2**x for x in range(10)): #In Python 2.x, use `xrange()`.
    ...

ыражения @Generator работают так же, как определение ручного генератора (как в Грег Хьюджилл ответ), с синтаксисом, похожим на понимание списка. Они оцениваются лениво - это означает, что они не генерируют список в начале операции, что может привести к гораздо лучшей производительности на больших итерациях.

Так что этот генератор работает, ожидая, пока его не спросят о значении, а затем спрашиваяrange(10) для значения, удваивая это значение и передавая его обратно вfor петля. Это повторяется до тех пор, поrange() генератор не дает больше значений.

 Gareth Latty04 мая 2012 г., 02:00
@ AshwiniChaudhary Whoops, исправлено.
 Gareth Latty04 мая 2012 г., 01:35
@ TomWijsman Мой ответ - одна строка - и предполагать, что одна строка всегда лучше, чем несколько строк, это безумие. Иногда больше строк более читабельно. Что касается более сложной отладки, то это просто неправда. Как я уже говорил в своем другом комментарии, есть причина, по которой все встроенные функции Python 3 теперь ленивы, когда в 2.x они создавали списки.
 Gareth Latty04 мая 2012 г., 01:26
@ TomWijsman Не думаю, что это менее читабельно. Если бы вы действительно хотели, вы могли бы сделатьdoubles = (x*2 for x in range(10)) а затем перебратьdoubles. Если вы сравниваете его с вашим ответом - пониманием списка - мы буквально говорим о разных скобках вне выражения. Как это может быть менее читабельным или поддерживаемым?
 Ashwini Chaudhary04 мая 2012 г., 01:40
@ Lattyware Я думаю, что ОП хочет 2,4,8,16,32 ... а ваше решение дает 2,4,6,8,10 ....

Ты захочешь использовать список пониманий за эт

print [x**2 for x in xrange(10)] # X to the 2nd power.

а такж

print [x**x for x in xrange(10)] # X to the Xth power.

Синтаксис понимания списка следующий:

[EXPRESSION for VARIABLE in ITERABLE if CONDITION]

Под капотом он действует какmap и функция фильтра:

def f(VARIABLE): return EXPRESSION
def c(VARIABLE): return CONDITION

filter(c, map(f, ITERABLE))

Пример приведен:

def square(x): return x**2

print map(square, xrange(10))

а такж

def hypercube(x): return x**x

print map(hypercube, xrange(10))

Который можно использовать в качестве альтернативного подхода, если вам не нравятся списки. Вы также можете использовать цикл for, но это отойдет от Python идиоматики ...

 Gareth Latty04 мая 2012 г., 01:21
Не правда. Мой ответ ссылается на видео, которое я сделал, в котором объясняются списочные выражения наряду с выражениями генератора, а также диктом и набором пониманий. Выражения генератора ленивы, и поэтомуочен отличается от понимания списка. Если мы сделаем цикл до пяти миллионов, ваше решение создаст список из0*2 через4999999*2, затем перебери его. Выражение генератора будет вычислять их по мере необходимости.
 Gareth Latty04 мая 2012 г., 01:28
Это полностью верно, и все же в этом случае мы говорим о другом наборе скобок вокруг выражения. Не похоже, что эта оптимизация будет стоить нам времени, читабельности или чего-то еще, так почему бы не сделать это? Цитата опускается, когда мы говорим о чем-то, что не стоит нам ни времени, ни усилий, а наличие хорошей практики часто означает, что вам не нужно беспокоиться об этом, когда это важн
 Gareth Latty04 мая 2012 г., 01:13
Создание списка и последующее его циклирование не является оптимальным, и это не синтаксис для списка comp (это выражение, а не функция, это итеративный, а не список, и в конце может быть оператор if ).
 Gareth Latty04 мая 2012 г., 01:53
Я не голосовал против других ответов - фактически, я проголосовал против двух других. Реальность такова, что отладка в Python с помощью выражений генератора прекрасна - отладка в Python почти всегда выполняется с помощьюprint() заявления и поэтому это действительно не имеет значения. Если худшее становится худшим, вы можете просто обернуть свой генератор вlist() чтобы увидеть его вывод. Я отладил множество проблем в Python при использовании генераторов. Что касается простоты - выражение генератора не сложнее, чем понимание списк
 Tom Wijsman04 мая 2012 г., 01:18
@ Lattyware: это оптимально, это то, что делает выражение генератора. Обратите внимание, как ваш ответ ссылается на список понимания ...;)

как насчет обобщения операции итерации / приращения для лямбда-функции, чтобы вы могли сделать что-то вроде этого:

for i in seq(1, 9, lambda x: x*2):
    print i
...
1
2
4
8

Гдеseq определяется ниже:

#!/bin/python
from timeit import timeit

def seq(a, b, f):
    x = a;
    while x < b:
        yield x
        x = f(x)

def testSeq():
    l = tuple(seq(1, 100000000, lambda x: x*2))
    #print l

def testGen():
    l = tuple((2**x for x in range(27)))
    #print l

testSeq();
testGen();

print "seq", timeit('testSeq()', 'from __main__ import testSeq', number = 1000000)
print "gen", timeit('testGen()', 'from __main__ import testGen', number = 1000000)

Разница в производительности не так уж велика:

seq 7.98655080795
gen 6.19856786728

[РЕДАКТИРОВАТЬ

Для поддержки обратной итерации и с аргументом по умолчанию ...

def seq(a, b, f = None):
    x = a;
    if b > a:
        if f == None:
            f = lambda x: x+1
        while x < b:
            yield x
            x = f(x)
    else:
        if f == None:
            f = lambda x: x-1
        while x > b:
            yield x
            x = f(x)

for i in seq(8, 0, lambda x: x/2):
    print i

Примечание: это ведет себя иначе, чемrange/xrange в каком направлении</> test выбирается знаком итератора, а не разностью между начальными и конечными значениями.

Ваш ответ на вопрос