Функция изменяет переменную, объявленную вне функции

Как сделать так, чтобы переменная вне функции не изменялась?

Есть список:

list_1 = ['cat', 'dog', 'horse', 'cow', 'mouse']

Есть функция:

def animals(mass):
    new_list = []
    if len(mass) == 1:
        new_list.append(mass[0])
    else:
        while len(mass) > 0:
            new_list.append(mass[0])
            del mass[0]
            
            if len(mass) == 1:
                new_list.append(mass[0])
                break

    return new_list

После выполнения animals(list_1),
список list_1 режется и становится просто ['mouse']

В проекте эта функция добавляет кнопки на основании списка, но при повторном обращении к этому списку, добавляется всего одна кнопка.

Как можно оставить список без изменений?


Ответы (4 шт):

Автор решения: кирилл

можно создать копию списка и работать с ней с помощью copy https://docs.python.org/3/library/copy.html вот документация

→ Ссылка
Автор решения: S. Nick

Вам надо выполнить глубокое копирование:

list_copy = copy.deepcopy(list_1)

Или изменить логику, например так:

list_1 = ['cat', 'dog', 'horse', 'cow', 'mouse']

def animals(mass):
    new_list = []

    if len(mass) == 1:                                           # ???
        new_list.append(mass[0])
    else:
#        while len(mass) > 0:
        for i, item in enumerate(mass):                          # +++
            new_list.append(f'{item}_{i}')
#            del mass[0]
            
            if len(mass) == i-1:                                 # +++
                new_list.append(f'{item}_{i}')
#                break

    return new_list      

n_list = animals(list_1)

print(f'\nn_list = {n_list}') #
print(f'list_1 = {list_1}\n') #    

Выведет:
введите сюда описание изображения

→ Ссылка
Автор решения: Amgarak

Ваша функция изменяет исходный список list_1, так как фактически вы ссылаетесь на объекты её ячеек. Можно просто создать копию(срез) списка и работать уже с ним, тогда исходные данные не будут изменены.

list_1 = ['cat', 'dog', 'horse', 'cow', 'mouse']

def animals(mass):
    new_list = []
    mass_copy = mass[:]  # Создаем копию/срез списка
    if len(mass_copy) == 1:
        new_list.append(mass_copy[0])
    else:
        while len(mass_copy) > 0:
            new_list.append(mass_copy[0])
            del mass_copy[0]
            
            if len(mass_copy) == 1:
                new_list.append(mass_copy[0])
                break

    return new_list

result = animals(list_1)
print(result)
print(list_1)  # Список list_1 остается как был 
→ Ссылка
Автор решения: Opium

Нужно отметить, что методы списков, в отличие от строковых методов, изменяют сам список, а потому результат выполнения затирает значения внутри ИМЕЮЩЕГОСЯ списка. Чтобы этого не происходило , просто копируйте ваш список и работайте в функции с копией. Например вот так:

list_1 = ['cat', 'dog', 'horse', 'cow', 'mouse']
list_2 = list_1.copy() 
...
animals(list_2)
→ Ссылка