添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

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

我想修改我传递给函数的一个变量的值。我读到Python中所有的东西都是通过值传递的,但一定有一个简单的技巧。例如,在Java中你可以传递 Integer Long 等的引用类型。

  • How can I pass an integer into a function by reference?
  • What are the best practices?
  • 1 个评论
    请看这个,这是一个很好的方法,尽管有点复杂,但可以把你的ints包在一个匿名类中(它是可变的),它的行为就像一个 "引用"。 stackoverflow.com/a/1123054/409638 i.e. ref = type('', (), {'n':1})
    python
    function
    pass-by-reference
    pass-by-value
    CodeKingPlusPlus
    CodeKingPlusPlus
    发布于 2013-03-01
    13 个回答
    mgilson
    mgilson
    发布于 2021-10-31
    已采纳
    0 人赞同

    在Python中并不完全是这样的。Python 将引用传递给对象。在你的函数中,你有一个对象 -- 你可以自由地突变这个对象(如果可能的话)。然而,整数是 不变的 .一个变通的办法是在一个可以变异的容器中传递整数。

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

    这充其量是丑陋/笨拙的,但在 Python 中你不会做得更好。原因是在Python中,赋值(=)是将右手边的任何对象与左手边的任何对象绑定在一起*(或将其传递给适当的函数)。

    Understanding this, we can see why there is no way to change the value of an 不变的 object inside a function -- you can't change any of its attributes because it's 不变的, and you can't just assign the "variable" a new value because then you're actually creating a new object (which is distinct from the old one) and giving it the name that the old object had in the local namespace.

    通常情况下,解决方法是简单的return你想要的对象。

    def multiply_by_2(x):
        return 2*x
    x = 1
    x = multiply_by_2(x)
    

    *在上述第一个例子中,3实际上被传递给了x.__setitem__

    难怪我们对这些术语感到困惑。 这里我们把它描述为 按对象调用 而在这里,它被描述为 逐值传递 . 在其他地方,它被称为 "通过参考",并对它的实际含义打上了星号......基本上,问题是社区还没有搞清楚 怎么说呢
    没错,而且我宁愿根本不提 "传递",因为这正是人们所困惑的。在Python中。 every expression 评估为一个引用(即所有的值都是引用)。当你创建一个对象时,你得到一个引用。当你调用一个函数时,它返回一个引用。当你访问一个属性时,左边的东西是一个引用。基本上,这都是引用。对对象所做的任何事情都必须通过指向它的引用来完成。所以,当你传递东西时,它们也是引用,这并不奇怪。
    Python 引用与 Java 引用完全相同。而Java引用是根据JLS指向对象的指针。而且在语义上,Java/Python引用和C++指向对象的指针之间基本上是完全双射的,没有其他东西可以描述这种语义。"它们不需要被解除引用" 好吧, . 操作符只是解除了左边的引用。操作符在不同的语言中可以是不同的。
    支持通过引用传递标量对于跨语言的兼容性非常有用(例如将C++转换为Python)。
    @RonInbar -- 我不太清楚你在这里想说什么。 Python 不是 C# (或 Java) 的装箱和拆箱的概念。 在参考实现中。 everything 只是一个 PyObject 。 当你调用一个Python函数时,Python并不知道(或关心)被传递的类型。 事实上,你可以用不同的类型多次调用同一个函数(考虑到内置的 str )。 在函数接口层面上,并没有对基元进行特殊的命名,AFAIK。 是的,这也是Python函数调用相比之下有点昂贵的原因之一。
    Gabe
    Gabe
    发布于 2021-10-31
    0 人赞同

    大多数需要通过引用传递的情况是需要返回一个以上的值给调用者。一个 "最佳实践 "是使用多个返回值,这在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
        
    Uri
    Uri
    发布于 2021-10-31
    0 人赞同

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

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

    注意事项。

  • nonlocal was introduced in python 3
  • If the enclosing scope is the global one, use global instead of nonlocal.
  • 但你需要为此只使用一个特定的变量名。这减少了 "通过引用 "的兴趣,如果它是准确的引用的话。
    Sergey Kovalev
    Sergey Kovalev
    发布于 2021-10-31
    0 人赞同

    也许这不是pythonic方法,但你可以这样做

    import ctypes
    def incr(a):
        a += 1
    x = ctypes.c_int(1) # create c-var
    incr(ctypes.ctypes.byref(x)) # passing by ref
        
    abarnert
    abarnert
    发布于 2021-10-31
    0 人赞同

    真的,最好的做法是退一步,问问你是否真的需要这样做。 Why 你想修改你传递给函数的一个变量的值吗?

    如果你需要做一个快速的黑客,最快速的方法是传递一个 list 持有整数,并在每次使用它的时候贴上一个 [0] ,正如mgilson的答案所演示的。

    如果你需要为更重要的东西做这件事,写一个 class ,它有一个 int 作为属性,所以你可以直接设置它。当然,这迫使你为这个类和属性想出一个好的名字--如果你想不出来,回去再读几遍这个句子,然后用 list

    更普遍的是,如果你试图把一些 Java 习语直接移植到 Python 中,你就做错了。即使有直接对应的东西 (如 static / @staticmethod ),你仍然不希望在大多数 Python 程序中使用它,因为你会在 Java 中使用它。

    JAVA不通过引用来传递整数(整数或任何对象。有框的对象在赋值时也被替换)。
    @LuisMasuelli 好吧,盒式基元就像对象一样被对待,唯一阻止他们像OP所希望的那样使用的是盒式基元是不可变的(因为基元本身也是不可变的,所以整个东西都是不可变的,只能在变量层面上改变。)
    z33k
    一个好的用例是计算一个递归函数内部的调用次数(总数,不是深度)。你需要一个可以在所有分支调用中递增的数字。一个标准的int并不能满足要求。
    0 人赞同

    A numpy单元素数组 是可变的,但对于大多数情况下,它可以被评估为一个数字的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)
    

    output:

    mheyman
    mheyman
    发布于 2021-10-31
    0 人赞同

    也许比list-of-length-1的技巧稍稍多一点的自我记录是古老的空类型技巧。

    def inc_i(v):
        v.i += 1
    x = type('', (), {})()
    x.i = 7
    inc_i(x)
    print(x.i)
        
    或者把数字包在一个类中。 github.com/markrages/python_mutable_number
    Chris Pugmire
    Chris Pugmire
    发布于 2021-10-31
    0 人赞同

    正确的答案是使用一个类,并把值放在类里面,这可以让你完全按照你的愿望通过引用传递。

    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)
        
    是的,编写一个简单的封装类,并简单地总是访问内部对象,这才是正途。
    newacct
    newacct
    发布于 2021-10-31
    0 人赞同

    在 Python 中,每个值都是一个引用 (指向一个对象的指针),就像 Java 中的非原语。另外,和 Java 一样,Python 只有通过值传递。所以,从语义上讲,它们是相当相同的。

    既然你在问题中提到了 Java,我想看看你是如何在 Java 中实现你的愿望的。如果你能在Java中显示出来,我可以告诉你如何在Python中完全等效地做到这一点。

    shruti
    shruti
    发布于 2021-10-31
    0 人赞同
    class PassByReference:
        def Change(self, var):
            self.a = var
            print(self.a)
    s=PassByReference()
    s.Change(5)     
        
    JillAndMe
    JillAndMe
    发布于 2021-10-31
    0 人赞同
    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
        
    recursive
    recursive
    发布于 2021-10-31
    0 人赞同

    在 Python 中,所有的东西都是按值传递的,但是如果你想修改一些状态,你可以改变传递给方法的列表或对象里面的一个整数的值。

    我认为,因为 everything is passed by value 并不是真的。引用文件。【替换代码1
    AN88
    列表、对象和字典是通过引用传递的
    如果那是真的,在一个函数中对参数的赋值将反映在调用处。正如Astery所引述的那样,传递是通过值进行的,这些值是对象的引用。
    devp
    devp
    发布于 2021-10-31
    0 人赞同

    整数是 不变的 在Python中,一旦它们被创建,我们就不能通过使用变量的赋值操作来改变它们的值,我们要让它指向其他的地址而不是之前的地址。

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

    def swap(a,b):
        return b,a
    a,b=22,55
    a,b=swap(a,b)
    print(a,b)
    

    To change the reference a variable is pointing to we can wrap 不变的 data types(int, long, float, complex, str, bytes, truple, frozenset)内的可变数据类型(字节数组、列表、集合、Dict).

    #var is an instance of dictionary type
    def change(var,key,new_value):
        var[key]=new_value