如何在 Python 中通过引用传递整数?
我想修改传递给函数的变量的值。我读到 Python 中的所有内容都是通过值传递的,但是必须有一个简单的技巧。例如,在 Java 中可以传递 Integer、 Long等引用类型。
Integer
Long
在 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__。
3
x.__setitem__
实际上,最好的做法是退一步问自己是否真的需要这样做。要修改传递给函数的变量的值吗?
如果需要快速修改,最快的方法是传递一个保存整数的 list,并在每次使用它时都使用 [0],正如 mgilson 的答案所示。
list
[0]
如果您需要执行更重要的操作,那么编写一个包含 int作为属性的 class,这样您就可以设置它。当然,这会迫使您为这个类和属性想出一个好名字ーー如果您想不出任何东西,请回头再读几遍这个句子,然后使用 list。
int
class
更一般地说,如果您试图将某些 Java 习惯用法直接移植到 Python,那么您的做法是错误的。即使有直接对应的东西(比如 static/@staticmethod) ,您仍然不希望在大多数 Python 程序中使用它,因为您会在 Java 中使用它。
static
@staticmethod
在 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
global
也许这不是蟒蛇的方式,但你可以做到这一点
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'])