В некоторых языках вы можете передать параметр по ссылке или по значению, используя специальное зарезервированное слово, например ref или val . Когда вы передаете параметр функции Python, он никогда не изменяет значение параметра при выходе из функции. Единственный способ сделать это - использовать глобальное зарезервированное слово (или, как я понимаю в настоящее время).
Пример 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, что параметр является либо значением, либо параметром ссылки вместо использования global?
Во-вторых, на кембриджских экзаменах уровня A теперь говорится, что функция возвращает одно значение, а процедура возвращает более одного значения. В 80-х годах меня учили, что функция имеет оператор возврата, а процедура - нет. Почему сейчас это неверно?
n
быть изменено, вы используете новую переменнуюsquare
для хранения результата вашего расчета.Ответы:
Вы не можете изменить неизменяемый объект, например
str
илиtuple
, внутри функции в 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 = 2 b = 3 a, b = foo(a, b) # a == 4; b == 9
Когда вы возвращаете такие значения, они возвращаются как кортеж, который, в свою очередь, распаковывается.
edit: Другой способ подумать об этом заключается в том, что, хотя вы не можете явно передавать переменные по ссылке в 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
источник
clear_a
получает ссылкуz
и сохраняет эту ссылку вx
. Затем он сразу же переходитx
к ссылке на другой массив. Об исходномz
массиве забываютclear_a
, но фактически не изменяют. Он остается без изменений при возврате в глобальную область видимости. Сравните с тем,clear_b
что принимает ссылкуz
и затем работает непосредственно с ним, никогда не создавая новый массив или иным образом не указываяx
и что-то другое.y = x
,y: y.pop()
а затем называетсяclear_b(z)
, г еще получил опустели ... Так что нам нужно что - то вродеy = list(x)
создать копию х (список (х) объяснил здесь )run_thread = [True] t= threading.Thread(target=module2.some_method, \ args=(11,1,run_thread)) --do something - and when you want to sop run_thread[0] =False
По сути, существует три вида «вызовов функций»:
Python - это язык программирования ПРОПУСКАЕМЫХ ОБЪЕКТОВ.
Во-первых, важно понимать, что переменная и значение переменной (объекта) - это две разные вещи. Переменная «указывает» на объект. Переменная - это не объект. Очередной раз:
ПЕРЕМЕННАЯ НЕ ОБЪЕКТ
Пример: в следующей строке кода:
>>> x = []
[]
- пустой список,x
- это переменная, которая указывает на пустой список, ноx
сама по себе не является пустым списком.Рассмотрим переменную (
x
в приведенном выше случае) как поле, а «значение» переменной ([]
) как объект внутри поля.ПРОХОДИТЬ ПО ОБЪЕКТУ (Случай в 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]
ПРОЙТИ ПО СПРАВОЧНИКУ:
Поле из вызывающей функции передается вызываемой функции. Неявно содержимое поля (значение переменной) передается вызываемой функции. Следовательно, любое изменение содержимого поля в вызываемой функции будет отражено в вызывающей функции.
ПРОЙТИ ПО СТОИМОСТИ:
Новый блок создается в вызываемой функции, и копии содержимого блока из вызывающей функции сохраняются в новые блоки.
Надеюсь это поможет.
источник
Хорошо, я попробую это сделать. Python передает по ссылке на объект, что отличается от того, что вы обычно понимаете как «по ссылке» или «по значению». Вот пример:
def foo(x): print x bar = 'some value' foo(bar)
Итак, вы создаете строковый объект со значением «некоторое значение» и «привязываете» его к переменной с именем
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
указанием на него).Это не неуклюжее. Когда вы понимаете, как это работает, это красивая, элегантная и эффективная система.
источник
str
ings,tuple
s и другие объекты неизменяемы . Если вы передаете изменяемый объект, например alist
, вы можете изменить его внутри функции без необходимости возвращать его, потому что все параметры функции являются указателями на те же объекты, которые вы передали.Надеюсь, следующее описание хорошо подытожит это:
Здесь нужно учитывать две вещи - переменные и объекты.
Пример:
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
Пример:
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']]
Пример:
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]
источник
Python не является ни передачей по значению, ни по ссылке. Это больше похоже на то, что «ссылки на объекты передаются по значению», как описано здесь :
Вот почему это не передача по значению. Потому как
def append(list): list.append(1) list = [0] reassign(list) append(list)
возвращает [0,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
источник
Технически python не передает аргументы по значению: все по ссылке. Но ... поскольку в Python есть два типа объектов: неизменяемые и изменяемые, вот что происходит:
Неизменяемые аргументы эффективно передаются по значению : строка, целое число, кортеж - все это неизменяемые типы объектов. Хотя технически они «передаются по ссылке» (как и все параметры), поскольку вы не можете изменить их на месте внутри функции, они выглядят / ведут себя так, как будто они передаются по значению.
Изменяемые аргументы эффективно передаются по ссылке : списки или словари передаются по указателям. Любое изменение на месте внутри функции, например (append или del), повлияет на исходный объект.
Так устроен Python: никаких копий, все передаются по ссылке. Вы можете явно передать копию.
def sort(array): # do sort return array data = [1, 2, 3] sort(data[:]) # here you passed a copy
И последнее, что я хотел бы упомянуть, какая функция имеет свою область видимости.
def do_any_stuff_to_these_objects(a, b): a = a * 2 del b['last_name'] number = 1 # immutable hashmap = {'first_name' : 'john', 'last_name': 'legend'} # mutable do_any_stuff_to_these_objects(number, hashmap) print(number) # 1 , oh it should be 2 ! no a is changed inisde the function scope print(hashmap) # {'first_name': 'john'}
источник
Так что это немного тонкий момент, потому что, хотя Python передает переменные только по значению, каждая переменная в Python является ссылкой. Если вы хотите иметь возможность изменять свои значения с помощью вызова функции, вам нужен изменяемый объект. Например:
l = [0] def set_3(x): x[0] = 3 set_3(l) print(l[0])
В приведенном выше коде функция изменяет содержимое объекта List (который является изменяемым), поэтому на выходе будет 3 вместо 0.
Я пишу этот ответ только для того, чтобы проиллюстрировать, что означает «по значению» в Python. Приведенный выше код - плохой стиль, и если вы действительно хотите изменить свои значения, вы должны написать класс и вызвать методы внутри этого класса, как предлагает MPX.
источник
y = [a for a in x]; y[0] = 3; return y
x = foo(x)
.Дается ответ
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 это кажется очень неуклюжим. Является ли это лучшим из имеющихся у нас методов?
Это не только неуклюже, но и включает в себя изменение исходного параметра каким-либо образом вручную, например, путем изменения исходного параметра в список: или копирования его в другой список вместо того, чтобы просто сказать: «используйте этот параметр как значение» или «используйте этот. в качестве справки ". Может ли быть простой ответ: для этого нет зарезервированного слова, но это отличная работа?
источник
Учтите, что переменная - это блок, а значение, на которое она указывает, - это «вещь» внутри блока:
1. Передача по ссылке: функция использует одно и то же поле, а значит, и вещь внутри.
2. Передача по значению: функция создает новый ящик, копию старого, включая копию того, что находится внутри него. Например. Java- функции создают копию коробки и вещи внутри нее, которая может быть: примитивом / ссылкой на объект. (обратите внимание, что скопированная ссылка в новом поле и исходная ссылка по-прежнему указывают на один и тот же объект, здесь ссылка ЯВЛЯЕТСЯ вещью внутри поля, а не объектом, на который она указывает)
3. Передача по объектной ссылке : функция создает блок, но он включает в себя то же, что и первоначальный блок. Итак, в Python :
а) если объект внутри указанного поля является изменяемым , внесенные изменения будут отражены в исходном поле (например, списки)
б) если объект неизменяемый (например, строки Python и числовые типы), тогда поле внутри функции будет содержать то же самое, ДО ТОГО, КАК вы попытаетесь изменить его значение. После изменения элемент в блоке функции становится совершенно новым по сравнению с исходным. Следовательно, id () для этого блока теперь будет указывать идентичность новой вещи, которую он включает .
источник
class demoClass: x = 4 y = 3 foo1 = demoClass() foo1.x = 2 foo2 = demoClass() foo2.y = 5 def mySquare(myObj): myObj.x = myObj.x**2 myObj.y = myObj.y**2 print('foo1.x =', foo1.x) print('foo1.y =', foo1.y) print('foo2.x =', foo2.x) print('foo2.y =', foo2.y) mySquare(foo1) mySquare(foo2) print('After square:') print('foo1.x =', foo1.x) print('foo1.y =', foo1.y) print('foo2.x =', foo2.x) print('foo2.y =', foo2.y)
источник
В Python передача по ссылке или по значению связана с фактическими объектами, которые вы передаете. Таким образом, если вы передаете, например, список, вы фактически выполняете этот проход по ссылке, поскольку список является изменяемым объектом. Таким образом, вы передаете указатель на функцию и можете изменить объект (список) в теле функции.
Когда вы передаете строку, эта передача осуществляется по значению, поэтому создается новый строковый объект, и когда функция завершается, он уничтожается. Так что все связано с изменяемыми и неизменяемыми объектами.
источник
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)
Вывод
0x50d43700 #with you might give another hex number deppend on your memory 0x50d43700
источник
def foo(var): print(id(var)) var = 1234 print(id(var)) x = 123 print(id(x)) # I think the id() give the ref... foo(x) print(id(x))