Страницы

Поиск по вопросам

воскресенье, 9 февраля 2020 г.

Каков механизм изменения значения переменных в цикле for Python

#python_3x #циклы #ссылки


Каким образом изменяется значение списков forenames и surnames, если мы явно не меняем
их значения? Это связано с names, какую роль это играет во внешнем цикле и как добавляя
в него элемент, мы меняем значения списков forenames и surnames? 

def get_forenames_and_surnames():

    forenames = []  
    surnames = [] 

    for names, filename in ((forenames, "forenames.txt"),
                                 (surnames, "surnames.txt")):

        for name in open(filename, encoding='utf8'):
            names.append(name.rstrip())
    return forenames, surnames

    


Ответы

Ответ 1



Для начала пример: a = [1, 2, 3] b = a a.append(4) print(a) print(b) Output [1, 2, 3, 4] [1, 2, 3, 4] Вопрос: почему поменялись оба списка, когда меняли только список a? Ответ: В Python переменные являются ссылками (идентификаторами) на хранящиеся в памяти объекты, поэтому: a = [1, 2, 3] означает - создай объект типа list, заполни его значениями 1, 2, 3 и присвой ссылку на этот объект переменной a. b = a - присвой переменной b ссылку, которая хранится в переменной a (которая в свою очередь указывает на объект). Теперь две переменных указывают на один и тот же объект. a.append(4) - найди объект по ссылке в переменной a и добавь в него элемент 4. Помним, что объект у нас один, на него указывают a и b. Если сделаем b.append(4), результат будет такой же. Упрощённая схема связи переменных и объектов: Теперь разберём ваш код: # Вспомогательная функция для печати идентификатора объекта def print_object_id(var_name, obj): # Функция id возвращает идентификатор объекта. obj_id = id(obj) print('{:X} - "{:s}" id'.format(obj_id, var_name)) def get_forenames_and_surnames(): print("===Назначение переменных===") forenames = [] # Печатаем, какой идентификатор присвоился переменной forenames print_object_id("forenames", forenames) surnames = [] # Печатаем, какой идентификатор присвоился переменной surnames print_object_id("surnames", surnames) print("\n===Внешний цикл for===") for names, filename in ((forenames, "forenames.txt"), (surnames, "surnames.txt")): ### На каждой итерации переменной "names" присваивается новый идентификатор: # В первой итерации это идентификатор переменной forenames # Вo второй итерации это идентификатор переменной surnames print_object_id("names", names) for name in open(filename, encoding='utf8'): # По идентификатору хранящемся в "names", Python ищет у # себя объект (в нашем случае это объект типа List) # и вызывает у этого объекта метод "append". # В итоге, новой элемент добавляется к списку. names.append(name.rstrip()) return forenames, surnames get_forenames_and_surnames() Output ===Назначение переменных=== 7F552E85B388 - "forenames" id 7F552E85B3C8 - "surnames" id ===Внешний цикл for=== 7F552E85B388 - "names" id ### Тот же самый, что и у forenames 7F552E85B3C8 - "names" id ### Тот же самый, что и у surnames

Ответ 2



Наиболее сложной является команда for names, filename in ((forenames, "forenames.txt"), (surnames, "surnames.txt")): То, что за in, есть кортеж из 2 элементов: (forenames, "forenames.txt") (первый элемент) (surnames, "surnames.txt") (второй элемент) Значит, тело цикла будет повторяться только дважды: первый раз для names == forenames и filename == "forenames.txt" второй раз для names == surnames и filename == "surnames.txt" В каждой из этих итераций выполнится тело цикла: for name in open(filename, encoding='utf8'): names.append(name.rstrip()) Значит, в первой итерации откроется файл forenames.txt и строки из него добавятся к списку forenames, в другой то же самое с файлом surnames.txt и списком surnames.

Комментариев нет:

Отправить комментарий