Python передает аргумент в функцию - PullRequest
0 голосов
/ 10 декабря 2010

, ребята, я получил вопрос о передаче изменяемого объекта в функцию

со следующим кодом, я ожидал, что на выходе будет [0,0,0], а на выходе - [0,1, 2,3]

означает ли это, что аргумент фактически копируется, а затем отправляется внутрь функции?

def lala(a):
    n = [0, 0 , 0]
    a = n

a = [0,1,2,3]

lala(a)

print a

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

большое спасибо!

Ответы [ 6 ]

8 голосов
/ 10 декабря 2010

Python имеет больше смысла, если вы думаете о присоединении тегов имен к объектам, а не о вставке объектов в именованные блоки.

def lala(a):
    n = [0, 0 , 0]
    a = n

Вот что происходит.

  1. Выполучение параметра (в данном случае списка) и присвоение ему имени a.
  2. Вы создаете новый список и присваиваете ему имя n.
  3. .список, который вы назвали n дополнительное имя a.
  4. Оба имени, a и n, являются локальными для функции lala, поэтому они "истекают" после завершения функции.
  5. Список, созданный в функции, теперь не имеет имен, и Python отбрасывает его.

Другими словами, a - это не ящик, в который вы можете поместить новыйсписок.Это имя, которое вы дали список, который вы получили.Позже вы переназначаете это имя в список, который вы также назвали n.

Другие предложили назначить фрагмент, a[:] = n, который использует ссылку на элементы в списке, а не на сам список.Когда вы делаете это, имя a все еще указывает на тот же список;его содержимое было только что заменено.Поскольку это тот же список, который был передан в функцию, любые имена, по которым он известен за пределами функции, будут «видеть» новое содержимое.

3 голосов
/ 10 декабря 2010

kindall предоставил отличное объяснение на мой взгляд, но мой предпочтительный способ сделать что-то вроде этого - заставить функцию возвращать изменение, а не возиться со ссылками.

def lala():
     n = [0, 0, 0]
     return n

a = [0, 1, 2, 3]

a = lala()

print a # prints [0, 0, 0]
2 голосов
/ 10 декабря 2010

Python не имеет функции вызова по ссылке.Там нет общего способа сделать это.

Если вы знаете, что ваш аргумент будет списком, и вы хотите, чтобы он принял другое значение, вы можете написать его так:

def lala(a):
    a[:] = [0,0,0]
2 голосов
/ 10 декабря 2010

вы можете использовать a[:] = n внутри функции. это называется назначением среза

1 голос
/ 10 декабря 2010

Это потому, что функция делает новую метку "a" для своей области видимости.Затем это «а» затмевает «а», которое вы определили вне функции.Таким образом, новая метка a назначается новому объекту [0,0,0,0] Если вы напишите:

def lala(a):
    a.pop()

a = [0,1,2,3,4]
lala(a)
print(a)

Вы увидите, что a = [0,1,2,3], потому что pop() фактически изменяет объект, на который указывает метка 'a'.(при назначении просто измените на какой объект указывает данная метка)

0 голосов
/ 10 декабря 2010

Обратите внимание на разницу между вашей функцией и этой:

def lala(a):
    a[0] = 7

a = [0,1,2,3]
lala(a)
print a   # prints [7, 1, 2, 3]
...