Skip to content

Latest commit

 

History

History
278 lines (217 loc) · 8.74 KB

For.md

File metadata and controls

278 lines (217 loc) · 8.74 KB

Цикл for и функция range()


Цикл for может обходить любой итерируемый объект.

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

Следующие 2 метода эквивалентны:

    for number in range(5):
        print('number = ', number)

    for num in [0, 1, 2, 3, 4]:
        print('num = ', num)

    # Вывод
    
    # ('number = ', 0)
    # ('number = ', 1)
    # ('number = ', 2)
    # ('number = ', 3)
    # ('number = ', 4)
    
    # ('num = ', 0)
    # ('num = ', 1)
    # ('num = ', 2)
    # ('num = ', 3)
    # ('num = ', 4)

Цикл for при работе со словарями dict

Цикл for применим к словарям, использование словаря эквивалентно вызову метода .keys() который возвращает список из ключей словаря, по скольку словари не отсортированная структура, полученные ключи тоже не отсортированы, так что вывод в цикле, тоже будет не отсортирован, мы просто получаем ключи и так их и выводим.

Следующие 2 метода for эквивалентны:

    a_dict = {"two": 2, "three": 3, "one": 1 }

    print('a_dict.keys() = ', a_dict.keys())
    print('type = ', type(a_dict.keys()))

    for key in a_dict:
        print(key)

    for key in a_dict.keys():
        print(key)
    
    # a_dict.keys() =  dict_keys(['two', 'three', 'one'])
    # type =  <class 'dict_keys'>
    
    # two
    # three
    # one
    
    # two
    # three
    # one

Для того чтобы отсортировать ключи, используется спец функция sorted() она отсортирует полученные ключи, которые уже и можно будет выводить.

    a_dict = {"C": 3, "B": 2, "A": 1}
    keys = a_dict.keys()

    keys = sorted(keys)

    print('a_dict.keys() = ', a_dict.keys())
    print('sorted(a_dict.keys()) = ', keys)

    for key in keys:
        print(key)

    # Вывод
    # a_dict.keys() =  dict_keys(['C', 'B', 'A'])
    # sorted(a_dict.keys()) =  ['A', 'B', 'C']
    # A   
    # B
    # C

Таким образом можно вывести ключи, и если требуется по ним можно получать и значения по этим ключам:

    a_dict = {"C": 3, "B": 2, "A": 1}
    keys = sorted(a_dict.keys())

    for key in keys:
        print(key, ' = ', a_dict[key])

    # Вывод
    # A  =  1
    # B  =  2
    # C  =  3

Блок else в цикле for

У циклов есть блок else который исполняется всегда если не было использовано оператора break. Такая же логика используется и в while.

Блок else срабатывает по завершению работы цикла, но при условии, что цикл завершен естественным образом, если же цикл завершен оператором brake то блок else не сработает.

    for i in range(1, 11):
        print('i = ', i)
    else:
        print('Блок else')

    for i in range(1, 11):
        if i == 5:
            print('i равен 5 ')
            break
        print('i = ', i)
    else:
        print('Блок else')

    for i in range(1, 11):
        if i == 5:
            print('i равен 5 ')
            continue
        print('i = ', i)
    else:
        print('Блок else')
    
    # Вывод
    # i = 1 i = 2 i = 3 i = 4 i = 5 i = 6 i = 7
    # i = 8 i = 9 i = 10
    # Блок else
    
    # i = 1 i = 2 i = 3 i = 4
    # i равен 5 
    
    # i = 1 i = 2 i = 3 i = 4
    # i равен 5 
    # i =  6 i =  7 i =  8 i = 9 i = 10
    # Блок else

Функция range() и arange()


Первоначально в версии python2 существовало 2 метода range() и xrange() метод range() просто создавал обычный список со всеми значениями, метод xrange() являлся генератором, спец класса range и как обычный генератор, создавал новый элемент последовательности только при обращении к нему, что позволяло экономить память, и не хранить созданный список в памяти полностью.

Метод xrange() работал лучше, чем обычный range(), дело в том что python сам по себе очень прожорливый на память язык программирования, к примеру обычный пустой список в python весит 64 байта

    import sys

    list_1 = list()
    print('list_1 = ', list_1)
    print('Empty list in bytes = ', sys.getsizeof(list_1))

    # Вывод
    # ('list_1 = ', [])
    # ('Empty list in bytes = ', 64)

Если же мы используем для генерации списка range() из старой версии python2, для генерации 1000 элементов, то получим следующий результат:

    import sys

    list_2 = list(range(1, 1001))
    print('list_2 = ', list_2)
    print('Not empty in bytes = ', sys.getsizeof(list_2))
    
    # Вывод
    # list_2 =  [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 ...
    # 995, 996, 997, 998, 999, 1000]
    # Not empty in bytes =  9112

Можно увидеть что хранить весь список в памяти просто невыгодно, он занимает 9112 байт по этому и использовался метод xrange() ибо будучи генератором, он не хранил всю последовательноcть в памяти, а генерировал новое значение сразу при обращении, далее в версии python3 метод range() был удален, а метод xrange() был переименован в метод range() с ним мы теперь и работаем.

Если запустить следующий код в версии Python-2 то, можно увидеть разницу методов.

    func_range = range(1, 11)
    print('type(func_range) = ', type(func_range))
    print('func_range = ', func_range)

    func_xrange = xrange(1, 11)
    print('type(func_xrange) = ', type(func_xrange))
    print('func_xrange = ', func_xrange)

    # Вывод
    # ('type(func_range) = ', <type 'list'>)
    # ('func_range = ', [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
    
    # ('type(func_xrange) = ', <type 'xrange'>)
    # ('func_xrange = ', xrange(1, 11))

Тут и можно увидеть что метод range() генерирует список, то время как xrange() создает спец тип данных.


Современный метод range(start, end, step)

Метод range() генерирует последовательность элементов, с заданным шагом:

    var_1 = range(1, 11)
    print('var_1 = ', var_1)

    var_2 = range(1, 11, 2)
    print('var_2 = ', var_2)

    var_3 = range(1, 11, -1)
    print('var_3 = ', var_3)

    # Вывод
    # ('var_1 = ', [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
    # ('var_2 = ', [1, 3, 5, 7, 9])
    # ('var_3 = ', [])

Метод range() создает не список, а особый объект, по которому можно итерироваться при помощи цикла for но списком не является, и для превращения в список требуется указать это явно:

    some = range(1, 11)
    print(some)
    print(type(some))

    my_list = list(some)
    print(my_list)
    print(type(my_list))

    # Вывод
    # range(1, 11)
    # <class 'range'>
    
    # [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    # <class 'list'>