Как сделать цикл for более понятным в python?

В настоящее время я преподаю немного программирования на Python некоторым довольно молодым студентам. Я хочу, чтобы они узнали, как написать цикл for.

Пока что я показал это студентам так:

for i in range(1,11):
    print(i)

который дает цикл, где i иду от 1 до 10.

Моя проблема в том, что студентам кажется странным, что им нужно написать 11 в качестве второго аргумента для range(1,11) когда они хотят, чтобы цикл увеличился до 10. Студенты находят это непонятным.

В C/C++ и родственных языках такой цикл можно записать так:

for(int i = 1; i <= 10; i++)
    { /* do something */ }

Мне кажется, что способ выражения цикла C++ более интуитивен, поскольку в этом случае я могу явно записать 1 и 10, которые являются первым и последним значениями, которые я хочу, чтобы переменная цикла принимала.

Работая с циклами for в python, я в конечном итоге говорю студентам что-то вроде: "мы просто должны признать, что нам нужно написать 11, когда мы хотим, чтобы цикл перешел на 10, это немного раздражает, но вам просто нужно научиться что функция диапазона работает таким образом ". Я не рад этому; Я хочу, чтобы они узнали, что программирование - это весело, и я боюсь, что подобные вещи делают его менее увлекательным.

Поскольку python часто описывается как язык, подчеркивающий удобочитаемость, я подозреваю, что есть более хороший способ выразить цикл for, способ, который вызвал бы меньше путаницы для моих учеников.

Есть ли лучший и/или менее запутанный способ выразить этот вид цикла for в языке Python?

Ответы

Ответ 1

Напомните им, что есть причина, по которой функция диапазона работает таким образом. Одним из его полезных свойств является то, что число циклов, которое будет выполнено, равно второму аргументу range минус первый аргумент.

Я думаю, что люди получают действительно зацикливаться на этом, но дело в том, for циклов в Python очень отличается от C. В C, for петель в основном оберткой цикла.

Эти два примера должны помочь показать разницу между циклами в C и Python.

# for(int x=1; x <= 10; x++)
x = 1
while x <= 10:
    print(x)
    x += 1


i = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]  # range(1, 11)
for x in i:
    print(i)

Но, честно говоря, настоящая проблема здесь в том, что все циклы и массивы легче понять и работать с ними, если они начинаются с нуля, а не с одного. Пожалуйста, рассмотрите возможность корректировки ваших примеров, чтобы начать с нуля.

Таким образом, если вы хотите выполнить цикл 10 раз, вы используете число 10.

   # for(int x=0; x < 10; x++)
x = 0
while x < 10:
    print(x)
    x += 1


i = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]  # range(10)
for x in i:
    print(i)

Ответ 2

Вы можете показать им этот код для лучшего понимания:

start = 1
length = 10
for i in range(start,start+length):
    print(i)

Есть также еще одна функция, которая работает как это, она называется ломтик.

Ответ 3

Я считаю, что есть два простых способа ответить на вопрос. 1) Один из способов объяснения этого ответа - использование математического обозначения полузакрытого интервала [a, b). В этот интервал включена одна конечная точка (в данном примере это "a"), но не другая конечная точка ("b"). Итак, для вашего примера,

for i in range(1,11):
     print(i)

(1,11) является полузакрытым интервалом, где a и b равны 1 и 11 соответственно.

2) Вы также можете объяснить, используя следующие примеры

    for i in range(1,11)  //in python 
        {do something}

    for(int i=1;i<11;i++)  //in C++
        {do something}

В обоих случаях я выполняю от 1 до 10. Это кажется мне более интуитивным.

Ответ 4

Покажите им два варианта C++:

# using <= operator
for(int i = 1; i <= 10; i++)
    { /* do something */ }

# using < operator
for(int i = 1; i < 11; i++)
    { /* do something */ }

И скажите им, что функция range Python работает как вторая.

Ответ 5

Ваши студенты получат пользу от изучения на раннем этапе, так как большинство языков программирования используют индексацию с нуля. Самый простой способ понять функцию Python range() - это использовать ее только с одним аргументом.

for i in range(10):
    # will iterate exactly 10 times with i going from 0 to 9

В мире с нулями это имеет смысл.

Диапазон Python в нотации интервалов имеет исключительную верхнюю границу: [0.. [10, в отличие от включающего интервала, который по умолчанию используют некомпьютерные инженеры [1... 10]

Учитывая это, параметр, переданный функции диапазона, понимается как исключительное значение "стоп".

Когда вы используете дополнительный параметр для обеспечения начальной точки, было бы непоследовательным внезапно обрабатывать значение остановки по-разному. Это приведет к тому, что диапазон (0,10) будет вести себя иначе, чем диапазон (10), и это будет очень запутанным.

Основное отличие от C состоит в том, что range() подразумевает сравнение "меньше чем" вместо "меньше или равно":

 for i in range(A,B):   # for (i=A;i<B;i++)
     ...

Вы можете предоставить своим студентам функцию "inclusiveRange", чтобы они могли начать работу, не понимая основанных на нулях концепций.

 def inclusiveRange(start=0,end,step=1):
     return range(start,end+1,step)

Они могли бы использовать это вместо range()

 for i in inclusiveRange(1,10):
     ... # will iterate from 1 to 10 inclusively

Недостатком является то, что ученикам придется "отучиться" от циклов, когда они начнут использовать индексы списков или вычислять позиции в системе координат. Вы могли бы сэкономить их много - 1 и off by one в будущем, получив их на борту с индексированием на основе нуля сегодня.

Ответ 6

Моя проблема в том, что студентам кажется странным, что им нужно написать 11 в качестве второго аргумента для диапазона (1,11), когда они хотят, чтобы цикл увеличился до 10. Студенты находят это непонятным.

Путаница исходит не от утверждения for, а от range. Что вам нужно сделать, это разделить ваше объяснение на две части: во-первых, for итераций это аргумент, и не заботится о содержании аргумента. Так

for i in [1,2,3]:
    {*do something*}

повторяется в списке с 3 элементами.

Теперь range определяется как полуоткрытый интервал целых чисел a <= x < b потому что он имеет много хороших математических свойств, таких как

len(range(a, b)) == b - a
len(range(a)) == a
range(a, a) == []
range(a, b) + range(b, c) == range(a, c)

и если определение range будет закрытым интервалом, программистам придется вносить коррективы с -1 здесь и там.

Это хороший пост в блоге на Subj.

Ответ 7

Это не "более" или "менее" понятно, это о том, как вы это описываете:

  • for x in something: перебирает значения из итерируемого something как переменную x. Итак, что вам нужно, это объяснить "что возвращается range(...) ".
  • range(start, end,...) возвращает объект, который производит последовательность целых чисел от начала (включительно) до остановки (исключая). Просто покажи им help(range)

А у тебя то, что ты спрашиваешь, это "как сделать цикл for более похожим на C?"

Есть несколько способов сделать это:


def nrange(start, num_elements, step=1):
    """Similar to 'range', but second argument is number of elements."""
    return range(start, start + step*num_elements, step)


def inclusive_range(start_or_stop, stop=None, step=1):
    if stop is None:
        start = 0
        stop = start_or_stop+1
    else:
        start = start_or_stop
        stop = stop + step
    return range(start, stop, step)


_default_update_func = lambda item: item+1
def c_like_iterator(start, test_func, update_func=_default_update_func):
    cur_value = start
    while test_func(cur_value):
        yield cur_value
        cur_value = update_func(cur_value)

for i in nrange(1, 10):
    print(i)

for i in inclusive_range(1, 10):
    print(i)

for i in inclusive_range(10):  # this will give 11 elements because both 0 and 10 values are included
    print(i)

for i in c_like_iterator(1, lambda x: x<=10, lambda x: x+1):
    print(i)

for i in c_like_iterator(1, lambda x: x<11, lambda x: x+1):
    print(i)

for i in inclusive_range(1, -10, -1):
    print(i)

Ответ 8

Попробуй это:

for i in range(10):
    print(i+1)

или же

list_of_numbers = range(1,11)

for number in list_of_numbers:
    print(number)

Ответ 9

Важно, чтобы они понимали стандартный способ, которым список и массив всегда начинаются с 0. Чтобы было проще понять, покажите им приведенный ниже код, который будет легко понять, почему массив начинается с индекса 0. не избегайте сложности, упростите ее.

for i in range(10):
    i+=1
    print(i)

или же

for i in range(10):
    print(i+1)

Ответ 10

Проблема не в понимании цикла for, а в понимании диапазона, исключая конечную точку. Один из способов увидеть это - рассматривать части диапазона как столбы и сегменты забора; построение "забора" с дальностью (10) дает вам забор с 10 столбами забора == |

| - | - | - | - | - | - | - |

Однако числа, которые вы видите, считают сегменты забора == - вы должны быть слева от столба забора (|), который будет 0-1-2-3-4-5-6-7-8-9

Если вы добавите начальный диапазон (1,10), он по-прежнему строит забор с 10 столбами забора, но ваши индексы смотрят только на все, по крайней мере, с одним сегментом забора, поэтому первый столб забора не является частью вашего диапазона. Но когда ваши индексы начинаются с 0 для первого поста, на который вы смотрите, вы получаете 1-2-3-4-5-6-7-8-9; все еще нет 10, потому что наш оригинальный забор был только 10 должностями. Таким образом, либо вы строите забор из 11 столбов и игнорируете все с менее чем 1 сегментом (диапазон (1,11)), либо вы строите забор из 10 столбов и притворяетесь, что слева от него есть еще один сегмент (диапазон (0,10) ) +1).

Изменение размера шага более чем на 1 означает, что вы учитываете только каждый 2/3/и т.д. Столб забора, начиная с первого, поэтому, если осталось больше столбов забора, но больше нет для подсчета, остальные в конце обрезаются и игнорируются.

Ответ 11

Я думаю, что одно из самых важных понятий в обучении информатике - понять, как работает индексирование массивов. Вы должны потратить некоторое время, объясняя эту концепцию студентам, в ясной форме с простыми примерами. Начиная с LISP, почти все языки программирования начинаются с нуля. Python и C++ ничем не отличаются. В Python простые lists могут быть использованы в качестве примеров для иллюстрации концепции.

#a simple list
In [15]: list1 = [1,2,3,4,5,6,7,8,9,10,11]
In [23]: len(list1) #number of items in the list
Out[23]: 11
In [26]: list1[0] #the first item in the list
Out[26]: 1
In [25]: print("list1 starts at index {}. The number at this index is {}.".format(list1.index(1), list1[0]))
list1 starts at index 0. The number at this index is 1.
In [37]: list1[10] #the last item in the list
Out[37]: 11
In [19]: print("list1 ends at index {}. The number at this index is {}.".format(len(list1)-1, list1[-1]))
list1 ends at index 10. The number at this index is 11.

Как вы заметите, значения "число" опережают значения "индекс" на 1. Что если список list1 начинается с 0 и заканчивается 11, то значения индекса и числа 'number' будут одинаковыми, но количество элементов в списке увеличится на 1 и это потому, что мы включили 0. Удерживайте эту мысль для момент, когда нам понадобится это:

In [29]: list2 = [0,1,2,3,4,5,6,7,8,9,10,11]
In [31]: len(list2) #total number of items in list
Out[31]: 12
In [32]: list2[0]
Out[32]: 0
In [35]: list2[11]
Out[35]: 11

Запомните синтаксис range() соответствии с документацией: range(start, end, step). Мы проигнорируем шаг для этого обсуждения.

Итак, теперь, если я хочу создать список, аналогичный списку list2 используя range(), я могу использовать приведенную выше информацию для формирования обобщенного синтаксиса для range():

Syntax: range(start, len(list2)+start), where start is the first item in the range, 
        list2 is a list and len(list2) is its size and the end is len(list2) + start

Чтобы поместить это в список, я просто передаю приведенное выше в качестве аргумента функции list(). Не важно разбираться в мелочах этой функции и использовать только для иллюстрации. Таким образом, мы получаем:

In [39]: list3 = list(range(0,len(list2)+0))    
In [40]: list3
Out[40]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]    
In [41]: list2 == list3 #both lists are equivalent
Out[41]: True
In [42]: len(list3)
Out[42]: 12          #same number of items as list2
In [46]: for i in range(0,len(list3)+0): #can replace list3 with list2 to get same results
    ...:     print(i, end=' ')
        ...:

0 1 2 3 4 5 6 7 8 9 10 11   #Output         

Цикл for повторяется по позициям индекса. Итак, i начинаю с позиции индекса 0 для элемента 0 (начало диапазона) и продолжается до позиции индекса 11 для элемента 11 (конец диапазона = 11 + 0).

Мы также можем проверить приведенный выше синтаксис для list1, который начинается с 1 и имеет длину 11.

In [6]: list(range(1,len(list1)+1))
Out[6]: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11] #same as list1 above
In [15]: for i in range(1,len(list1)+1):
    ...:     print(i, end=' ')
    ...:
1 2 3 4 5 6 7 8 9 10 11

Опять же, цикл for начинается с позиции индекса 0, как обычно, которая имеет элемент 1 (начало диапазона) и заканчивается в позиции индекса 10, которая имеет элемент 11 (конец диапазона = 11 + 1).

Теперь давайте посмотрим, как эта концепция также применима к C++. Мы используем ту же list2, который имеет 12 пунктов, т.е. len(list2) = 12. Опять же, не важно вдаваться в подробности всего в следующем примере, если студенты не совсем знакомы с массивами. Это только для иллюстрации:

#include <iostream>

using namespace std;

int main()
{
    int list2[12] = {0,1,2,3,4,5,6,7,8,9,10,11};
    std::cout << "Length of array list2 = " << (sizeof(list2)/sizeof(*list2)) << std::endl;
    for(int i=0;i<(sizeof(list2)/sizeof(*list2));i++)
    {
        cout<<i<<' ';
    }
    return 0;
}

//Output:
Length of array list2 = 12                                                                                            
0 1 2 3 4 5 6 7 8 9 10 11  #Output

Обратите внимание, что i<(sizeof(list2)/sizeof(*list2)) гарантирует, что конечный элемент извлекается из верхней границы массива, т.е. Элемент 11 из index = 12-1 = 11. Это именно то, что делает функция range(). Если я сделаю i<=(sizeof(list2)/sizeof(*list2)), это также выведет 12 в выводе, который не является элементом в list2 и выйдет за верхнюю границу массива. В Python функция range() более четко описывает границы массива. Итак, если я переопределил синтаксис range() приведенный выше, и позволю циклу for выполнять итерацию от 0 до элемента за пределами list2, увеличивая end на 1, я могу явно напечатать этот элемент:

In [13]: for i in range(0,len(list2)+1):
    ...:     if i>=len(list2):
    ...:         print("\nI am outside of list2: {}".format(i))
    ...:     else:
    ...:         print(i, end=' ')
    ...:
0 1 2 3 4 5 6 7 8 9 10 11
I am outside of list2: 12

Из этого обсуждения мы понимаем, что важно понимать итерацию цикла for как операцию на основе индекса, а range(start,end) - это встроенная функция Python, которая просто составляет значения между начальным и конечным диапазоном, включительно. начального значения и исключая конечного значения. Рассмотрим общее количество пройденных значений, включая элемент в начале (len(total) + start) как конец диапазона. Реализация цикла for не зависит от этого и учитывает только позиции индекса как в Python, так и в C++.

Ответ 12

Python для циклов работает иначе, чем традиционный стиль C для циклов, как описано здесь. Они функционируют больше как циклы "для каждого", найденные в других языках, или как метод итератора. Функция диапазона, используемая в вашем примере, является просто удобным способом создания коллекции целочисленных объектов для повторения. Причина, по которой "старт" включен, а "стоп" не включен, суммируется здесь довольно хорошо.

Когда дело доходит до объяснения этого новым программистам, я бы разбил это на части и объяснил, как работает цикл for, а затем объяснил, как можно использовать функцию диапазона, чтобы снабдить цикл for набором для итерации.

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

collection = [1, 2, 3]
for collectionMember in collection:
    print(collectionMember)

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

Простой способ создать коллекцию целых чисел, которую мы можем использовать для циклического перебора, - это использование функции range():

collection = range(1,4)
print(collection)
for collectionMember in collection:
   print(collectionMember)

Я знаю, что это не то, как циклы работают на других языках, но, по моему мнению, если вы учите их программировать на python, было бы легче сначала научить их, как работают версии на python, а затем, как только они получат твердое представление об этом, объясните как работают циклы на других языках и чем это отличается.

Ответ 13

Если вы в настоящее время пытаетесь научить их циклу for и оставляете урок подсчета от 0 до другого дня, то я бы просто перебрал список и вообще не использовал range.

Кроме того, возможность визуально просматривать содержимое списка, а затем сравнивать его с выводом функции print, поможет заставить его щелкнуть по ним.

list_to_loop = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

for i in list_to_loop:
    print(i)

Ответ 14

Прочитав ваш пост. Я думаю, что все не может быть обобщено. Отдельные вещи имеют свой путь. Концепция программирования одинакова, но на разных языках их представление или синтаксис различны. Итак, если бы я был вами, я поделюсь этой концепцией, а затем представлю эту концепцию в синтаксисе языка.

Концепция цикла одинаковы. (Initialize, condition, increment/decrement) Теперь, если вы хотите написать это на python, чем вы можете написать. Как например.

start, stop, step = 1, 11, 1
for i in range(start, stop, step):
    print(i, end=', ')
# Output: 1 2 3 4 5 6 7 8 9 10 
  • start: начальный номер последовательности, по default=0. (initialize) default=0. (initialize)
  • стоп: генерировать номера до, но не включая этот номер. (condition)
  • шаг: разница между каждым числом в последовательности, по default=1. (increment/decrement) default=1. (increment/decrement)

Уже примеры python for-loop приведены в другом ответе. Спасибо.

Ответ 15

Я догадываюсь, что дети младшего школьного возраста, и что нужно помнить при обучении, так это просто. Дайте им крошечные кусочки информации за один раз.
Вы хотите научить их петлям? Научи их только про цикл.

Предполагая, что они знают о строках и списках, можно пойти с этим примером:

somelist = ['a', 'b', 'c', 'd', 'e']
for letter in somelist:
    print(letter)