【问题标题】:passing by reference in Python在 Python 中通过引用传递
【发布时间】:2012-08-15 17:59:22
【问题描述】:

我有两个代码用于将参数传递给 Python 中的函数。 1-

def changeme( mylist ):
   mylist.append([1,2,3,4]);
   print "Values inside the function: ", mylist
   return

mylist = [10,20,30];
changeme( mylist );
print "Values outside the function: ", mylist

2-

def changeme( mylist ):
   mylist = [1,2,3,4]; 
   print "Values inside the function: ", mylist
   return

mylist = [10,20,30];
changeme( mylist );
print "Values outside the function: ", mylist

为什么在第一个代码中 mylist 是通过引用传递,而在第二个代码中是通过值传递?

【问题讨论】:

  • 他们都通过了相同的。不同之处在于您在名称被传递后对其执行的操作。
  • mylist 总是作为参考传递。
  • 哇,我真的很讨厌“Python 没有变量”的模因……至少,说,“Python 没有与 C 变量一样工作的变量。”更好的描述是,“在 C 中,变量是容器。在 Python 中,变量是标签。”
  • @Ned:我的回答和我链接的页面都没有这句话。取而代之的是:«虽然我们通常在 Python 中也提到“变量”(因为它是常用术语),但我们真正的意思是“名称”或“标识符”。在 Python 中,“变量”是值的名称标签,而不是带标签的框。» 这在很大程度上同意您的看法。在解决特定于命名、绑定在 Python 中的工作方式的问题时,语言参考使用的特定术语可能会有所帮助。

标签: python pass-by-reference


【解决方案1】:

在第一个示例中,您将信息附加到传入的列表中。在第二个示例中,您在返回之前重新分配 mylist 的本地值。两者做的事情不一样。

【讨论】:

    【解决方案2】:

    您需要意识到python中的赋值不会对左侧的对象进行操作。赋值在右侧创建对对象的新引用,并将该引用存储在左侧的名称中。因此,在您的第一个示例中,您更改了输入的列表,稍后您会看到该更改。在第二个示例中,在您的函数中创建一个对列表(在右侧创建)的新引用并将其绑定到本地(到函数)变量mylist。因此mylist 不再引用您输入到函数中的对象。

    【讨论】:

      【解决方案3】:

      修改对象和将名称重新分配给不同的对象是有区别的。对代码进行一个简单的更改,它可以始终如一地工作,因为现在它正在修改原始对象:

      def changeme( mylist ):
         mylist[:] = [1,2,3,4]; 
         print "Values inside the function: ", mylist
      

      附:除非您要返回一个值,否则函数末尾不需要 return

      【讨论】:

      • 因此,在您上面编写的代码中,mylist[:] 与传递给函数的参数相同,而在我的代码中,相同的名称被重新分配给不同的对象,是对吗?
      • @programmingIsFun,我想你明白了。
      【解决方案4】:

      这是因为您在函数 2 中将 mylist 分配给了其他对象:

      在python中,如果你将一个可变对象传递给一个函数,那么它被称为传递 通过引用,如果你传递一个不可变的对象,那么它被称为按值传递。

      mylist = [1,2,3,4]
      
      
      def changeme( mylist ):
         print (id(mylist))  #prints 180902348
      
         #at this point the local variable mylist points to [10,20,30] 
         mylist = [1,2,3,4];  #this reassignment changes the local mylist, 
      
         #now local mylist points to [1,2,3,4], while global mylist still points to [10,20,30] 
         print (id(mylist)) #prints 180938508 #it means both are different objects now 
      
         print ("Values inside the function: ", mylist)
         return
      
      mylist = [10,20,30];
      changeme( mylist );
      print ("Values outside the function: ", mylist)
      

      第一个:

      def changeme( mylist ):
         print (id(mylist))      #prints 180902348
      
         mylist.append([1,2,3,4]);  #by this it mean [10,20,30].append([1,2,3,4])
         #mylist is just a label pointing to [10,20,30]
         print (id(mylist))       #prints 180902348  , both point to same object
         print ("Values inside the function: ", mylist)
         return
      
      mylist = [10,20,30];
      changeme( mylist );
      print ("Values outside the function: ", mylist)
      

      【讨论】:

        【解决方案5】:

        Python 具有 按值传递 语义。总是。对象不是 Python 中的值。语言中的所有值都是引用(又名指针)。对象总是通过引用来操作的。人们为此想出了不同的名称,但无论他们如何称呼它,他们所描述的在语义上都等同于通过对象引用的值传递。

        无论何时传递或赋值,都会复制值(引用)。这意味着被调用的函数有自己的参数副本(这是一个引用)。因此分配给这个变量对调用者没有影响。从不。

        在您的第一个代码中,您没有分配参数。相反,您通过它指向的对象上的引用来调用方法。此方法修改对象。所以当然其他任何拥有指向同一个对象的引用的人都会看到它。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-07-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-01-28
          • 2020-12-06
          • 2017-08-12
          相关资源
          最近更新 更多