How does the value of the forenames and surnames lists change, unless we explicitly change their values? This is related to names , what role does it play in the outer loop and how, by adding an element to it, do we change the values ​​of the forenames and surnames lists?

 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 

    2 answers 2

    To begin with an example:

     a = [1, 2, 3] b = a a.append(4) print(a) print(b) 

    Output

     [1, 2, 3, 4] [1, 2, 3, 4] 

    Question : why did both lists change, when only list a changed?

    Answer:

    In Python, variables are references (identifiers) to objects stored in memory, therefore:

    • a = [1, 2, 3] means - create an object of type list , fill it with values 1, 2, 3 and assign a reference to this object to the variable a .
    • b = a - assignment to the variable b reference that is stored in the variable a (which in turn points to an object). Now two variables point to the same object.
    • a.append(4) - find an object by reference in the variable a and add element 4 . Remember that we have one object, point to it a and b . If we do b.append(4) , the result will be the same.

    Simplified communication scheme of variables and objects: enter image description here

    Now let's look at your code:

     # Вспомогательная функция для печати идентификатора объекта 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 
    • Thank you so much. Never received such a deep response. - korzh

    The most difficult is the team

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

    The fact that in is a tuple of 2 elements:

    • (forenames, "forenames.txt") (first element)
    • (surnames, "surnames.txt") (second element)

    This means that the loop body will be repeated only twice:

    • first time for names == forenames and filename == "forenames.txt"
    • second time for names == surnames and filename == "surnames.txt"

    In each of these iterations, the loop body will be executed:

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

    This means that in the first iteration, the forenames.txt file will open and the lines from it will be added to the forenames list, and the same with the surnames.txt file and the surnames list.