Python-2.7 class 方法导致对象成为
Python-2.7 class method causing objects to be
我在编写 class 定义时遇到问题,该定义导致调用 class 方法的对象发生更改。这种更改对象的行为是不可取的。我希望 class 方法能够将两个对象加在一起并吐出一个相同类型的新对象,即 a = b+c
我的 class 加法定义创建了一个 class 类型的新实例来保存两个对象组合的结果。麻烦的是,完成后,调用对象被更改为与两个对象的总和相同。
下面显示了不良行为的最小工作示例。该代码创建了 class 的两个实例,并使用一些随机数据对它们进行了初始化。每个对象包含两个等长列表和一个保存列表长度的整数。然后主代码打印每个对象的内容,调用addition方法并将数据存储到新对象中,最后打印原始对象的内容。
我在为 class 创建初始化时遇到了默认可变参数的问题 运行。我在想这是我不理解 Python 代码中何时发生可变行为以及如何防止它发生的另一个案例。
class myClass:
def __init__(self,list_a=None,list_b=None,list_count=0):
self.list_a=[] if list_b is None else list_a
self.list_b=[] if list_b is None else list_b
self.list_count = list_count
def add_data(self,ElementA,ElementB):
self.list_a.append(ElementA)
self.list_b.append(ElementB)
self.list_count = self.list_count + 1
def print_data(self):
print("Number of elements in this object is: %d"%self.list_count)
print("List A contents\n%s"%self.list_a)
print("List B contents\n%s\n"%self.list_b)
def addTogether(self,other):
test_data = myClass(self.list_a,self.list_b,self.list_count)
for i in range(0,other.list_count):
test_data.add_data(other.list_a[i],other.list_b[i])
return(myClass(test_data.list_a,test_data.list_b,test_data.list_count))
import random
object_array = [myClass() for i in range(2)]
#Loop over object array and fill each object with some data
for i in range(0,2):
NumData = int(10*random.random())
for m in range(0,NumData):
#Generate some junk data to insert into the list of this object
ListAData = int(10*random.random())
ListBData = int(10*random.random())
object_array[i].check_data()
object_array[i].add_data(ListAData,ListBData)
object_array[i].check_data()
object_array[0].print_data()
object_array[1].print_data()
new_data = object_array[0].addTogether(object_array[1])
new_data.print_data()
object_array[0].print_data()
object_array[1].print_data()
代码输出:
Number of elements in this object is: 2
List A contents
[6, 5]
List B contents
[8, 7]
Number of elements in this object is: 2
List A contents
[7, 6]
List B contents
[5, 3]
Number of elements in this object is: 4
List A contents
[6, 5, 7, 6]
List B contents
[8, 7, 5, 3]
Number of elements in this object is: 2
List A contents
[6, 5, 7, 6]
List B contents
[8, 7, 5, 3]
Number of elements in this object is: 2
List A contents
[7, 6]
List B contents
[5, 3]
对于 "defend" 传入列表,这些列表只是对对象的引用,只需在构造时对它们进行浅复制:
self.ListA=[] if ListA is None else ListA[:]
self.ListB=[] if ListB is None else ListB[:]
请注意,mylist[:]
复制列表(但不是内部对象,所以这是一个浅拷贝),并保护对现有源列表的任何外部引用。
目前您正在更改您在施工时获得的列表。
示例:
List A contents
[1, 7, 6, 9, 8, 8, 5, 0]
List B contents
[8, 9, 3, 5, 1, 3, 1, 8]
Number of elements in this object is: 8
List A contents
[7, 3, 1, 3, 9, 2, 8, 0]
List B contents
[8, 6, 6, 5, 0, 1, 8, 9]
Number of elements in this object is: 16
List A contents
[1, 7, 6, 9, 8, 8, 5, 0, 7, 3, 1, 3, 9, 2, 8, 0]
List B contents
[8, 9, 3, 5, 1, 3, 1, 8, 8, 6, 6, 5, 0, 1, 8, 9]
Number of elements in this object is: 8
List A contents
[1, 7, 6, 9, 8, 8, 5, 0]
List B contents
[8, 9, 3, 5, 1, 3, 1, 8]
Number of elements in this object is: 8
List A contents
[7, 3, 1, 3, 9, 2, 8, 0]
List B contents
[8, 6, 6, 5, 0, 1, 8, 9]
问题是您正在使用对象 A 中的列表而没有复制它们,因此当它们被更改时,原始列表也会被更改。可以找到许多解决此问题的方法 here. 我更喜欢使用 list()
。这将使您的 addTogether
方法如下所示:
def addTogether(self,other):
TestData = myClass(list(self.ListA),list(self.ListB),self.ListCount)
for i in range(0,other.ListCount):
TestData.add_data(other.ListA[i],other.ListB[i])
return(TestData)
您似乎在维护两个并行数组。通常这不是一个好主意。我建议考虑创建一个对象,其中包含存储在列表 A 和列表 B 中的数据的属性。然后您可以创建这些列表。合并列表就变得微不足道了。
你没看错,是同一个列表。使用 [:]
复制它,对我有用。
def addTogether(self,other):
TestData = myClass(self.ListA[:],self.ListB[:],self.ListCount)
for i in range(0,other.ListCount):
TestData.add_data(other.ListA[i],other.ListB[i])
return TestData
我在编写 class 定义时遇到问题,该定义导致调用 class 方法的对象发生更改。这种更改对象的行为是不可取的。我希望 class 方法能够将两个对象加在一起并吐出一个相同类型的新对象,即 a = b+c
我的 class 加法定义创建了一个 class 类型的新实例来保存两个对象组合的结果。麻烦的是,完成后,调用对象被更改为与两个对象的总和相同。
下面显示了不良行为的最小工作示例。该代码创建了 class 的两个实例,并使用一些随机数据对它们进行了初始化。每个对象包含两个等长列表和一个保存列表长度的整数。然后主代码打印每个对象的内容,调用addition方法并将数据存储到新对象中,最后打印原始对象的内容。
我在为 class 创建初始化时遇到了默认可变参数的问题 运行。我在想这是我不理解 Python 代码中何时发生可变行为以及如何防止它发生的另一个案例。
class myClass:
def __init__(self,list_a=None,list_b=None,list_count=0):
self.list_a=[] if list_b is None else list_a
self.list_b=[] if list_b is None else list_b
self.list_count = list_count
def add_data(self,ElementA,ElementB):
self.list_a.append(ElementA)
self.list_b.append(ElementB)
self.list_count = self.list_count + 1
def print_data(self):
print("Number of elements in this object is: %d"%self.list_count)
print("List A contents\n%s"%self.list_a)
print("List B contents\n%s\n"%self.list_b)
def addTogether(self,other):
test_data = myClass(self.list_a,self.list_b,self.list_count)
for i in range(0,other.list_count):
test_data.add_data(other.list_a[i],other.list_b[i])
return(myClass(test_data.list_a,test_data.list_b,test_data.list_count))
import random
object_array = [myClass() for i in range(2)]
#Loop over object array and fill each object with some data
for i in range(0,2):
NumData = int(10*random.random())
for m in range(0,NumData):
#Generate some junk data to insert into the list of this object
ListAData = int(10*random.random())
ListBData = int(10*random.random())
object_array[i].check_data()
object_array[i].add_data(ListAData,ListBData)
object_array[i].check_data()
object_array[0].print_data()
object_array[1].print_data()
new_data = object_array[0].addTogether(object_array[1])
new_data.print_data()
object_array[0].print_data()
object_array[1].print_data()
代码输出:
Number of elements in this object is: 2
List A contents
[6, 5]
List B contents
[8, 7]
Number of elements in this object is: 2
List A contents
[7, 6]
List B contents
[5, 3]
Number of elements in this object is: 4
List A contents
[6, 5, 7, 6]
List B contents
[8, 7, 5, 3]
Number of elements in this object is: 2
List A contents
[6, 5, 7, 6]
List B contents
[8, 7, 5, 3]
Number of elements in this object is: 2
List A contents
[7, 6]
List B contents
[5, 3]
对于 "defend" 传入列表,这些列表只是对对象的引用,只需在构造时对它们进行浅复制:
self.ListA=[] if ListA is None else ListA[:]
self.ListB=[] if ListB is None else ListB[:]
请注意,mylist[:]
复制列表(但不是内部对象,所以这是一个浅拷贝),并保护对现有源列表的任何外部引用。
目前您正在更改您在施工时获得的列表。
示例:
List A contents
[1, 7, 6, 9, 8, 8, 5, 0]
List B contents
[8, 9, 3, 5, 1, 3, 1, 8]
Number of elements in this object is: 8
List A contents
[7, 3, 1, 3, 9, 2, 8, 0]
List B contents
[8, 6, 6, 5, 0, 1, 8, 9]
Number of elements in this object is: 16
List A contents
[1, 7, 6, 9, 8, 8, 5, 0, 7, 3, 1, 3, 9, 2, 8, 0]
List B contents
[8, 9, 3, 5, 1, 3, 1, 8, 8, 6, 6, 5, 0, 1, 8, 9]
Number of elements in this object is: 8
List A contents
[1, 7, 6, 9, 8, 8, 5, 0]
List B contents
[8, 9, 3, 5, 1, 3, 1, 8]
Number of elements in this object is: 8
List A contents
[7, 3, 1, 3, 9, 2, 8, 0]
List B contents
[8, 6, 6, 5, 0, 1, 8, 9]
问题是您正在使用对象 A 中的列表而没有复制它们,因此当它们被更改时,原始列表也会被更改。可以找到许多解决此问题的方法 here. 我更喜欢使用 list()
。这将使您的 addTogether
方法如下所示:
def addTogether(self,other):
TestData = myClass(list(self.ListA),list(self.ListB),self.ListCount)
for i in range(0,other.ListCount):
TestData.add_data(other.ListA[i],other.ListB[i])
return(TestData)
您似乎在维护两个并行数组。通常这不是一个好主意。我建议考虑创建一个对象,其中包含存储在列表 A 和列表 B 中的数据的属性。然后您可以创建这些列表。合并列表就变得微不足道了。
你没看错,是同一个列表。使用 [:]
复制它,对我有用。
def addTogether(self,other):
TestData = myClass(self.ListA[:],self.ListB[:],self.ListCount)
for i in range(0,other.ListCount):
TestData.add_data(other.ListA[i],other.ListB[i])
return TestData