Python:将可变(?)对象传递给方法

时间:2013-10-06 06:02:13

标签: python object methods arguments mutable

我正在尝试使用一种方法来实现一个类,该方法使用一个对象来调用另一个方法,该对象是最低方法变异对象的类的一部分。我的实现有点复杂,所以我只发布一些虚拟代码,这样你就可以看到我在说什么:

class test:
    def __init__(self,list):
        self.obj = list
    def mult(self, x, n):
        x = x*n
    def numtimes(self, n):
        self.mult(self.obj, n)

现在,如果我创建了这种类型的对象并运行numtimes方法,它将不会更新self.obj:

m = test([1,2,3,4])
m.numtimes(3)
m.obj  #returns [1,2,3,4]

我希望它能给我[1,2,3,4,1,2,3,4,1,2,3,4]

基本上,我需要将self.obj传递给mult方法并让它变异self.obj,这样当我调用m.obj时,我会得到[1,2,3,4,1,2,3] ,4,1,2,3,4]代替[1,2,3,4]。

我觉得这只是理解python如何将对象作为方法的参数传递(比如它正在制作对象的副本,而不是我需要使用指针),但可能不是。我是python的新手,可以在这里使用一些帮助。

提前致谢!!

2 个答案:

答案 0 :(得分:3)

乘法x * n创建一个新实例,但不会改变现有列表。见这里:

a = [1]
print (id (a) )
a = a * 2
print (id (a) )

这应该有效:

class test:
    def __init__(self,list):
        self.obj = list

    def mult(_, x, n):
        x *= n

    def numtimes(self, n):
        self.mult(self.obj, n)

答案 1 :(得分:2)

请允许我承担更大的可变性主题。

列表是可变对象,支持可变操作和不可变操作。这意味着,就地更改列表的操作以及返回新列表的操作。相比之下,元组只是不可变的。

因此,要乘以列表,您可以选择两种方法:

  1. a * = b
  2. 这是可变操作,会在原位更改“a”。

    1. a = a * b
    2. 这是不可变的操作。它将评估'a * b',创建一个具有正确值的新列表,并为该新列表指定'a'。

      这里已经存在解决问题的方法。但是,我建议你稍微阅读一下。当您将列表(和其他对象)作为参数传递时,您只是将新引用或“指针”传递给同一列表。因此,在该列表上运行可变操作也将改变您传递的操作。当你写下:

      时,结果可能是一个非常微妙的错误
      >>> my_list = [1,2,3]
      >>> t = test(my_list)
      >>> t.numtimes(2)
      >>> my_list
      [1,2,3,1,2,3]  # Not what you intended, probably!
      

      所以这是我的最终建议。您可以选择使用可变操作,这很好。但是,然后从您的参数创建一个新副本,如下:

      def __init__(self,l):
          self.obj = list(l)
      

      或者使用不可变操作,并将它们重新分配给self:

      def mult(self, x, n):
          self.x = x*n
      

      或两者兼顾,保证额外安全无害:)