簡體   English   中英

導致對象成為對象的Python-2.7類方法

[英]Python-2.7 class method causing objects to be

我在編寫的類定義上遇到麻煩,該類定義導致調用類方法的對象被更改。 改變對象的這種行為是不希望的。 我希望類方法能夠將兩個對象加在一起並吐出相同類型的新對象,即a = b + c

我的附加類定義創建了一個新的類類型實例,以保存兩個對象組合的結果。 麻煩的是,完成后,調用對象將更改為與兩個對象的總和相同。

下面顯示了不良行為的最小工作示例。 該代碼創建一個類的兩個實例,並使用一些隨機數據對其進行初始化。 每個對象包含兩個相等長度的列表和一個保存列表長度的整數。 然后主代碼打印每個對象的內容,調用加法並將數據存儲在新對象中,最后打印原始對象的內容。

在為類創建初始化時,我遇到了默認可變參數的問題。 我在想這是我不了解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]

問題是您使用的是對象A中的列表,而沒有復制它們,因此當更改列表時,原始文檔也會被更改。 您可以在此處找到許多解決此問題的方法 我更喜歡使用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中的數據的屬性。然后,您可以創建這些對象的列表。 這樣,合並列表就變得微不足道了。

要“保護”傳入列表,這些列表只是對對象的匯總引用,只需在構造時對其進行淺表復制:

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]

您是對的,它是相同的列表。 使用[:]對其進行復制,對我有用。

    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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM