在 Python 中通过引用传递整数

如何在 Python 中通过引用传递整数?

我想修改传递给函数的变量的值。我读到 Python 中的所有内容都是通过值传递的,但是必须有一个简单的技巧。例如,在 Java 中可以传递 IntegerLong等引用类型。

  1. 如何通过引用将整数传递给函数?
  2. 最佳实践是什么?
160227 次浏览

在 Python 中,所有内容都是通过值传递的,但是如果您想要修改某种状态,您可以更改传递给方法的列表或对象中的整数的值。

在 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__

实际上,最好的做法是退一步问自己是否真的需要这样做。要修改传递给函数的变量的值吗?

如果需要快速修改,最快的方法是传递一个保存整数的 list,并在每次使用它时都使用 [0],正如 mgilson 的答案所示。

如果您需要执行更重要的操作,那么编写一个包含 int作为属性的 class,这样您就可以设置它。当然,这会迫使您为这个类和属性想出一个好名字ーー如果您想不出任何东西,请回头再读几遍这个句子,然后使用 list

更一般地说,如果您试图将某些 Java 习惯用法直接移植到 Python,那么您的做法是错误的。即使有直接对应的东西(比如 static/@staticmethod) ,您仍然不希望在大多数 Python 程序中使用它,因为您会在 Java 中使用它。

在 Python 中,每个值都是一个引用(指向对象的指针) ,就像 Java 中的非原语一样。而且,和 Java 一样,Python 只有 pass by 值。所以,在语义上,它们几乎是一样的。

既然你在问题中提到了 Java,我想看看你是如何在 Java 中实现你想要的东西的。如果你能在 Java 中展示它,我可以向你展示如何在 Python 中完全等效地完成它。

在大多数情况下,需要通过引用传递的是需要向调用者返回多个值的情况。一个“最佳实践”是使用多个返回值,这在 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
class PassByReference:
def Change(self, var):
self.a = var
print(self.a)
s=PassByReference()
s.Change(5)

也许比 list-of-length-1技巧更自我记录的是老的空类型技巧:

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


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

数字式单元数组是可变的,但是在大多数情况下,它可以像一个数值 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)

产出:

7

不是直接传递值,而是像传递值一样使用它。

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

警告:

  • nonlocal是在 python3中引入的
  • 如果封闭范围是全局范围,则使用 global而不是 nonlocal

也许这不是蟒蛇的方式,但你可以做到这一点

import ctypes


def incr(a):
a += 1


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

正确的答案是,使用一个类并将值放在类中,这样就可以按照您希望的方式通过引用进行传递。

class Thing:
def __init__(self,a):
self.a = a
def dosomething(ref)
ref.a += 1


t = Thing(3)
dosomething(t)
print("T is now",t.a)


class Obj:
def __init__(self,a):
self.value = a
def sum(self, a):
self.value += a
    

a = Obj(1)
b = a
a.sum(1)
print(a.value, b.value)// 2 2

整数在 python 中是 永恒不变,一旦它们被创建,我们就不能通过对变量使用赋值运算符来改变它们的值,我们使它指向其他地址而不是以前的地址。

在 python 中,一个函数可以 返回多个值,我们可以利用它:

def swap(a,b):
return b,a


a,b=22,55
a,b=swap(a,b)
print(a,b)

要更改变量指向的引用,我们可以将不可变数据类型(Int,long,float,plex,str,byte,truple,Frozenset)封装在可变数据类型(字节数组、列表、集合、结构)中。

#var is an instance of dictionary type


def change(var,key,new_value):
var[key]=new_value


var =dict()
var['a']=33
change(var,'a',2625)
print(var['a'])