Такие mutables объекты как назначенные по умолчанию аргументы в python

У меня есть сомнение с шагом аргументов в python, когда проходят как аргументы структуры данных mutables, например одна lista, и другой простой аргумент, следующей формы:

def  arguments_mutables(arg, arg1=[]):
    """returns arguments mutables"""
    arg1.append("Arguments")


print(arguments_mutables(1))
print(arguments_mutables(2))
print(arguments_mutables(3))

Последуй, что, переместив как аргумент стоимость для arg каждый так называемый увеличивает один indice для lista, они могут объяснять мне, потому что он сохраняет índice для каждого призыва к функции.

2
задан 27.03.2016, 01:06
2 ответа

Ответ Хавьера очень хороший, но только решает твой специфический случай, возможно то, что ты хочешь узнать действительно, состоит в том, что списки работают из-за ссылки.

То, что означает это, что, если ты создаешь список l1:

>>> l1 = []

В действительности то, что ты делаешь, состоит в том, чтобы перемещать его ссылку на объект. Следовательно, если потом ты создаешь другой список на основании первой:

>>> l2 = l1

Сейчас l2 у него есть ссылка на тот же объект. Чтобы это понимать лучше, он считает следующий пример:

>>> l1 = [1, 2, 3]
>>> l2 = l1
>>> l2.append(4)
>>> l1
[1, 2, 3, 4]
>>> l2
[1, 2, 3, 4]
>>> l1 is l2 # Tienen referencia al mismo objeto
True

Поскольку ты видишь, добавив элемент в l2 также происходит то же самое для l1 так как у обеих переменных есть ссылка на тот же список.

Происходит то же самое со словарями:

>>> d1 = {'nombre': 'Cesar'}
>>> d2 = d1
>>> d2['apellido'] = 'Bustios'
>>> d1
{'apellido': 'Bustios', 'nombre': 'Cesar'}
>>> d2
{'apellido': 'Bustios', 'nombre': 'Cesar'}
>>> d1 is d2 # Tienen referencia al mismo objeto
True

То, за чем оно последует, выполнив твой рукописный шрифт, чем в определении твоей функции arguments_mutables, ты создаешь в arg1 ссылка на список, именно поэтому последующие призывы к этой функции увеличивают размер списка, так как в действительности использована ссылка на тот же объект.

Если ты хочешь поддержать первоначальный объект, применив к нему какую-то операцию, что ты должен делать, состоит в том, чтобы перемещать его копию объекта. В случае списков это очень простое:

>>> l1 = [1, 2, 3, 4, 5]
>>> l2 = l1[:] # Una copia, un objeto nuevo
>>> l2.extend([6, 7, 8, 9, 10])
>>> l1
[1, 2, 3, 4, 5]
>>> l2
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> l1 is l2 # No tienen referencia al mismo objeto
False

В случае словарей, ты можешь использовать метод copy:

>>> d1 = {'nombre': 'Cesar'}
>>> d2 = d1.copy() # Una copia, un objeto nuevo
>>> d2['apellido'] = 'Bustios'
>>> d1
{'nombre': 'Cesar'}
>>> d2
{'apellido': 'Bustios', 'nombre': 'Cesar'}
>>> d1 is d2 # No tienen referencia al mismo objeto
False

Для более сложных словарей ты должен использовать copy.deepcopy.

Если у тебя есть функция, также ты можешь перемещать его копию, чтобы сохранять первоначальный объект. Считай следующую функцию:

import random

def extendedora(lista):
    lista.append(random.randint(6, 10))
    return lista

Сейчас, первый случай, используя тот же список:

>>> lista_original = [1, 2, 3, 4, 5]
>>> lista_extendida = extendedora(lista_original)
>>> lista_original
[1, 2, 3, 4, 5, 9]
>>> lista_extendida
[1, 2, 3, 4, 5, 9]
>>> lista_original is lista_extendida
True

Используя копию, чтобы поддерживать первоначальный список:

>>> lista_original = [1, 2, 3, 4, 5]
>>> lista_extendida = extendedora(lista_original[:])
>>> lista_original
[1, 2, 3, 4, 5]
>>> lista_extendida
[1, 2, 3, 4, 5, 6]
>>> lista_original is lista_extendida
False
5
ответ дан 24.11.2019, 14:41

Стандартная настройка оценены с левой стороны до правой стороны, когда она definiciГіn ее funciГіn он работает. Это значит, что expresiГіn оценен единственный раз, когда определяют ее funciГіn, и эта же самая "пред-вычисленная" стоимость используется для каждого вызова. Это особенно важно понимания, когда назначенный по умолчанию аргумент - объект mutable, такой как список или словарь: если ее funciГіn изменяет объект (например aГ±adiendo статья в список), стандартная настройка действительно изменена. Это обычно не та intenciГіn.

Функтион Дефинитионс

Por ejemplo, следующая funciГіn накопи аргументы, которые проходят с ним в последующих вызовах:

def f(a, L=[]):
  L.append(a)
  return L

print(f(1))
print(f(2))
print(f(3))

# Esto imprime
# [1]
# [1, 2]
# [1, 2, 3]

, Если ты не хочешь, чтобы стандартная настройка имелась между последующими призывами к ней funciГіn, ты можешь писать ее, таким образом:

def f(a, L=None):
  if L is None:
    L = []
  L.append(a)
  return L

print(f(1))
print(f(2))
print(f(3))

# Esto imprime
# [1]
# [2]
# [3]
2
ответ дан 24.11.2019, 14:41

Теги

Похожие вопросы