Python似乎将实例变量视为类变量

时间:2017-05-19 14:46:15

标签: python oop

我有一个实例变量似乎被视为类变量,因为它更改了对象的所有实例。

class DNA(object):

      def __init__(self,genes = pd.DataFrame(), sizecontrol=500, name='1'):
        self.name = name
        self.genes = genes  # This attribute should be an instance variable 
        self.GeneLen = self.genes.shape[1]
        self.sizecontrol = sizecontrol
        self.Features = []
        self.BaseFeats = []
        random.seed(self.name)

当我运行时,我得到以下内容:

 In[68]: df = pd.DataFrame(data)

 In[69]: x1 = DNA(genes=df)

 In[70]: x2 = DNA(genes=df)

 In[71]: x1.genes["dummy"] = 'test'

 In[72]: x2.genes["dummy"].head(4) 
 Out[72]:   
  0 test 
  1 test 
  2 test 
  3 test 

如何确保x1.genes不影响x2.genes?

2 个答案:

答案 0 :(得分:5)

这里有两个问题。

首先,数据框是可变对象,并且两个实例都引用同一个对象。您需要使用df.copy()为每个实例提供新副本。您也可以在__init__函数本身中复制数据帧。这将是“更安全”,因为可以确保您不会重复使用数据框,但这也可能会创建不必要的副本。

其次,与您的示例无关,提供可变默认参数genes = pd.DataFrame()存在问题。此数据框保存在未绑定的__init__函数中,就像它是该函数的成员数据一样(请参阅__init__.__func__.func_defaults)。相反,使用默认参数None或其他一些标记值,然后在genes is None时实例化新数据框。

答案 1 :(得分:5)

您的代码工作正常,因为genesDNA类实例的属性。

但是,您只创建了一个数据帧。您为其指定了名称df,并将其作为genesx1的属性x2

self.genes = genes

分配。由于分配永远不会复制数据,因此您仍然只有一个数据框在x1x2之间共享。

enter image description here

要解决此问题,您可以在将数据框传递给DNA构造函数或使用

之前制作数据框的副本
self.genes = genes.copy()

__init__方法中。