Функции Python вызывают по ссылке

В некоторых языках вы можете передать параметр по ссылке или значению с помощью специального зарезервированного слова, например ref или val. Когда вы передаете параметр функции Python, он никогда не изменяет значение параметра при выходе из функции. Единственный способ сделать это - использовать зарезервированное слово global (или, как я понимаю, в настоящее время).

Пример 1:

k = 2

def foo (n):
     n = n * n     #clarity regarding comment below
     square = n
     return square

j = foo(k)
print j
print k

будет показывать

>>4
>>2

показывая, что k будет изменяться

В этом примере переменная n никогда не изменяется

Пример 2:

n = 0
def foo():
    global n
    n = n * n
    return n

В этом примере переменная n изменяется

Есть ли способ в Python вызвать функцию и сказать Python, что параметр является либо значением, либо ссылкой, вместо использования глобальный?

Во-вторых, на экзаменах Cam уровня A теперь говорят, что функция возвращает значение single, тогда как процедура возвращает более одного значения. Меня учили, что функция имеет оператор возврата, а процедура в 80-е годы не выполняется. Почему это сейчас неправильно?

Ответ 1

Вы не можете передать простой примитив по ссылке в Python, но вы можете делать такие вещи, как:

def foo(y):
  y[0] = y[0]**2

x = [5]
foo(x)
print x[0]  # prints 25

Это странный способ обойти это. Обратите внимание, что в Python вы также можете вернуть более одного значения, что делает некоторые из вариантов использования для передачи по ссылке менее важными:

def foo(x, y):
   return x**2, y**2

a = 1
b = 2
a, b = foo(a, b)  # a == 2; b == 4

Когда вы возвращаете такие значения, они возвращаются как Tuple, который, в свою очередь, распаковывается.

изменить Другой способ подумать об этом состоит в том, что, хотя вы не можете явно передавать переменные по ссылке в Python, вы можете изменить свойства объектов, которые были переданы. В моем примере (и других) вы можете изменить членов списка, который был. Однако вы не смогли бы переназначить переданные в переменной целиком. Например, см. Следующие два фрагмента кода, которые выглядят так, как будто они могут сделать что-то подобное, но заканчиваются разными результатами:

def clear_a(x):
  x = []

def clear_b(x):
  while x: x.pop()

z = [1,2,3]
clear_a(z) # z will not be changed
clear_b(z) # z will be emptied

Ответ 2

Существует по существу три вида "вызовов функций":

  • Передать значение
  • Перейдите по ссылке
  • Передача по объектной ссылке

Python - это язык программирования PASS-BY-OBJECT-REFERENCE.

Во-первых, важно понимать, что переменная и значение переменной (объекта) являются двумя отдельными вещами. Переменная "указывает на" объект. Переменная не является объектом. Опять же:

ПЕРЕМЕННЫЙ НЕ ОБЪЕКТ

Пример: в следующей строке кода:

>>> x = []

[] - пустой список, x - переменная, указывающая на пустой список, но сам x не является пустым списком

Рассмотрим переменную (x, в приведенном выше случае) как поле и "значение" переменной ([]) как объект внутри поля.

PASS BY REFERENCE (случай в python):

Здесь "Ссылки на объекты передаются по значению".

def append_one(li):
    li.append(1)
x = [0]
append_one(x)
print x

Здесь оператор x = [0] делает переменную x (поле), которая указывает на объект [0]

В вызываемой функции создается новое поле li. Содержимое li является ТОЛЬКО как содержимое поля x. Оба поля содержат один и тот же объект. То есть обе переменные указывают на один и тот же объект в памяти. Следовательно, любое изменение объекта, на которое указывает li, также будет отражено объектом, на который указывает x.

В заключение, выход указанной программы будет:

[0, 1]

Примечание:

Если переменная li переназначается в функции, тогда li укажет на отдельный объект в памяти. x, однако, будет продолжать указывать на тот же объект в памяти, который он указывал ранее.

Пример:

def append_one(li):
    li = [0, 1]
x = [0]
append_one(x)
print x

Выходной сигнал программы будет:

[0]

ПРОСМОТР ПО ССЫЛКЕ:

Коробка от вызывающей функции передается вызываемой функции. Неявно, содержимое поля (значение переменной) передается вызываемой функции. Следовательно, любое изменение содержимого поля в вызываемой функции будет отражено в вызывающей функции.

PASS BY VALUE:

В вызываемой функции создается новое поле, а копии содержимого окна из вызывающей функции сохраняются в новых полях.

Надеюсь, что это поможет.

Ответ 3

Хорошо, я возьму на это удар. Python проходит по ссылке объекта, которая отличается от того, что вы обычно считаете "по ссылке" или "по значению". Возьмите этот пример:

def foo(x):
    print x

bar = 'some value'
foo(bar)

Итак, вы создаете строковый объект со значением "some value" и "привязываете" его к переменной с именем bar. В C это будет похоже на bar как указатель на "некоторое значение" .

Когда вы вызываете foo(bar), вы не проходите в bar. Вы передаете значение bar: указатель на "некоторое значение" . В этот момент есть два "указателя" на один и тот же строковый объект.

Теперь сравните это с:

def foo(x):
    x = 'another value'
    print x

bar = 'some value'
foo(bar)

Здесь разница. В строке:

x = 'another value'

вы фактически не изменяете содержимое x. На самом деле это даже не возможно. Вместо этого вы создаете новый строковый объект со значением "другое значение". Этот оператор присваивания? Он не говорит, что "перезаписать вещь x указывает на новое значение". Он говорит "обновить x, чтобы вместо этого указать на новый объект". После этой строки есть два строковых объекта: "некоторое значение" (с bar, указывающее на него) и "другое значение" (при этом x указывает на него).

Это не неуклюже. Когда вы понимаете, как это работает, это красиво элегантная, эффективная система.

Ответ 4

Надеемся, что следующее описание суммирует его хорошо:

Здесь есть две вещи - переменные и объекты.

  • Если вы передаете переменную, то она передается по значению, что означает, что изменения, внесенные в переменную внутри функции, являются локальными для этой функции и, следовательно, не будут отображаться глобально. Это скорее поведение типа C.

Пример:

def changeval( myvar ):
   myvar = 20; 
   print "values inside the function: ", myvar
   return

myvar = 10;
changeval( myvar );
print "values outside the function: ", myvar

O/P:

values inside the function:  20 
values outside the function:  10
  1. Если вы передаете переменные, упакованные внутри изменяемого объекта, например список, то изменения, внесенные в объект, отражаются глобально до тех пор, пока объект не будет повторно назначен.

Пример:

def changelist( mylist ):
   mylist2=['a'];
   mylist.append(mylist2);
   print "values inside the function: ", mylist
   return

mylist = [1,2,3];
changelist( mylist );
print "values outside the function: ", mylist

O/P:

values inside the function:  [1, 2, 3, ['a']]
values outside the function:  [1, 2, 3, ['a']]
  1. Теперь рассмотрим случай, когда объект переназначается. В этом случае объект относится к новой ячейке памяти, которая является локальной для функции, в которой это происходит и, следовательно, не отражается глобально.

Пример:

def changelist( mylist ):
   mylist=['a'];
   print "values inside the function: ", mylist
   return

mylist = [1,2,3];
changelist( mylist );
print "values outside the function: ", mylist

O/P:

values inside the function:  ['a']
values outside the function:  [1, 2, 3]

Ответ 5

Python не является ни передачей по значению, ни передачей по ссылке. Это больше из "ссылок на объекты передаются по значению", как описано здесь:

  1. Вот почему оно не передается по значению. Потому что

    def append(list):
        list.append(1)
    
    list = [0]
    reassign(list)
    append(list)
    

возвращает [0,1], показывая, что какая-то ссылка была явно передана, так как передача по значению вообще не позволяет функции изменять родительскую область.

Похоже на передачу по ссылке, а? Неа.

  1. Вот почему это не переход по ссылке. Потому что

    def reassign(list):
      list = [0, 1]
    
    list = [0]
    reassign(list)
    print list
    

возвращает [0], показывая, что исходная ссылка была уничтожена при переназначении списка. передача по ссылке вернула бы [0,1].

Для получения дополнительной информации смотрите здесь:

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

from copy import copy

def append(list):
  list2 = copy(list)
  list2.append(1)
  print list2

list = [0]
append(list)
print list

Ответ 6

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

l = [0]

def set_3(x):
    x[0] = 3

set_3(l)
print(l[0])

В приведенном выше коде функция изменяет содержимое объекта List (который изменяет), и поэтому выход равен 3 вместо 0.

Я пишу этот ответ только для иллюстрации того, что означает "по значению" в Python. Вышеприведенный код плохой стиль, и если вы действительно хотите изменить свои значения, вы должны написать класс и методы вызова в этом классе, как предлагает MPX.

Ответ 7

Ответ:

def set_4(x):
   y = []
   for i in x:
       y.append(i)
   y[0] = 4
   return y

и

l = [0]

def set_3(x):
     x[0] = 3

set_3(l)
print(l[0])

который является лучшим ответом, поскольку он делает то, что он говорит в вопросе. Однако это кажется очень неуклюжим способом по сравнению с VB или Pascal. Это лучший метод, который у нас есть?

Он не только неуклюж, он в некоторой степени мутирует исходный параметр вручную, например, изменив исходный параметр на список: или скопировав его в другой список, а не просто говоря: "используйте это параметр как значение" или "использовать это как ссылку". Может ли простой ответ быть без зарезервированного слова для этого, но это отличная работа вокруг?

Ответ 8

Вот кое-что, что я пытался, я не понимаю этого сам, хотя надеюсь, что кто-то может объяснить это

https://i.stack.imgur.com/xYlj3.png

Ответ 9

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

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

Ответ 10

Python уже звонит по ссылке.

возьмем пример:

  def foo(var):
      print(hex(id(var)))


  x = 1 # any value
  print(hex(id(x))) # I think the id() give the ref... 
  foo(x)

OutPut

  0x50d43700 #with you might give another hex number deppend on your memory 
  0x50d43700