Подтвердить что ты не робот

Передача целочисленного значения по ссылке в Python

Как передать целое число по ссылке в Python?

Я хочу изменить значение переменной, которую я передаю функции. Я прочитал, что все в Python проходит по значению, но должен быть простой трюк. Например, в Java вы можете передать ссылочные типы Integer, Long и т.д.

  • Как передать целое число в функцию по ссылке?
  • Каковы наилучшие методы?
4b9b3361

Ответ 1

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

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

x = [1]
change(x)
print x

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

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

Обычно обходным путем является просто возврат объекта, который вы хотите:

def multiply_by_2(x):
    return 2*x

x = 1
x = multiply_by_2(x)

* В первом примере выше, 3 фактически передается в x.__setitem__.

Ответ 2

В большинстве случаев вам нужно будет передать по ссылке, где вам нужно вернуть более одного значения обратно вызывающему. "Лучшей практикой" является использование нескольких возвращаемых значений, что намного проще делать на Python, чем на таких языках, как Java.

Вот простой пример:

def RectToPolar(x, y):
    r = (x ** 2 + y ** 2) ** 0.5
    theta = math.atan2(y, x)
    return r, theta # return 2 things at once

r, theta = RectToPolar(3, 4) # assign 2 things at once

Ответ 3

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

Если вам нужно сделать это для быстрого взлома, самым быстрым способом является передача list, удерживающего целое число, и привязка [0] к каждому его использованию, как демонстрирует ответ на сообщение от mgilson.

Если вам нужно сделать что-то более важное, напишите class, у которого есть int как атрибут, поэтому вы можете просто установить его. Конечно, это заставляет вас придумать хорошее имя для класса, а для атрибута - если вы ничего не можете придумать, вернитесь назад и снова прочитайте предложение несколько раз, а затем используйте list.

В более общем плане, если вы пытаетесь перенести некоторую Java-идиому прямо на Python, вы делаете это неправильно. Даже если есть что-то непосредственно соответствующее (как с static/@staticmethod), вы по-прежнему не хотите использовать его в большинстве программ Python только потому, что будете использовать его в Java.

Ответ 4

В Python каждое значение является ссылкой (указателем на объект), как и не-примитивы в Java. Кроме того, как и Java, Python имеет только пропуск по значению. Итак, семантически, они почти одинаковы.

Поскольку вы упоминаете Java в своем вопросе, я хотел бы видеть, как вы достигаете того, чего хотите в Java. Если вы можете показать его на Java, я могу показать вам, как сделать это в эквивалентном эквиваленте в Python.

Ответ 5

class PassByReference:
    def Change(self, var):
        self.a = var
        print(self.a)
s=PassByReference()
s.Change(5)     

Ответ 6

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

    import numpy as np
    def triple_var_by_ref(x):
        x[0]=x[0]*3
    a=np.array([2])
    triple_var_by_ref(a)
    print(a+1)

выход:

3

Ответ 7

Не точно передать значение напрямую, но использовать его так, как если бы оно было передано.

x = 7
def my_method():
    nonlocal x
    x += 1
my_method()
print(x) # 8

Предостережения:

  • nonlocal был введен в Python 3
  • Если охватывающая область является глобальной, используйте global вместо nonlocal.

Ответ 8

Возможно, немного более самодокументирующийся, чем трюк списка-1, это старый трюк с пустым типом:

def inc_i(v):
    v.i += 1

x = type('', (), {})()
x.i = 7
inc_i(x)
print(x.i)

Ответ 9

Может быть, это не питонский способ, но вы можете сделать это

import ctypes

def incr(a):
    a += 1

x = ctypes.c_int(1) # create c-var
incr(ctypes.ctypes.byref(x)) # passing by ref

Ответ 10

В Python все передается по значению, но если вы хотите изменить какое-либо состояние, вы можете изменить значение целого числа внутри списка или объекта, переданного методу.