Python 类成员变量使用缺省值初始化时要注意的一个坑

Python 类成员变量使用缺省值初始化时要注意的一个坑
标签(空格分隔): python2.7 python 3.6


考虑到如下场景:

定义class A,class A 包含成员变量 l 和 d, l为数组, d 为字典;
在 class A 的构造函数中使用缺省参数初始化 A 的成员变量 l 和 d ;

具体代码如下:

class A:
    def __init__(self, l=["name"], d={"key1": "test"}):
        self.l = l
        self.d = d

现在,在主逻辑函数中定义生成多个 A 的实例, 构造时使用构造函数的缺省值:

if __name__ == "__main__":
    a1 = A()
    a2 = A()
    print (id(a1.l), id(a1.d))
    print (id(a2.l), id(a2.d))

输出的结果如下:
python2.7
(56305416L, 56376040L)
(56305416L, 56376040L)

python3.6
2036954509384 2036953558112
2036954509384 2036953558112

可以看出,使用缺省值初始化的2个 A 的实例中,对应的成员变量 l 和 d 指向了同一个地址

现在假设需要在主逻辑函数中分别操作实例a1 和 a2:

if __name__ == "__main__":
    a1 = A()
    a2 = A()
    # print (id(a1.l), id(a1.d))
    # print (id(a2.l), id(a2.d))

    a1.l.extend(["a", "b", "C", "Xa"])
    a1.d["key"] = "value"

    print ("a1", a1.l, a1.d)
    print ("a2", a2.l, a2.d)

输出结果会如下:
a1 ['name', 'a', 'b', 'C', 'Xa'] {'key1': 'test', 'key': 'value'}
a2 ['name', 'a', 'b', 'C', 'Xa'] {'key1': 'test', 'key': 'value'}

只修改a1,但 a2 的成员变量同时也被改变了!

此问题实际场景中其中一个是在使用wxGride时会遇到:

class MyGrid(wx.grid.Grid):
    def __init__(self, parent, col_titles=["a", "b", "c"], data=[["1", "2", "3"]]):
        wx.grid.Grid__init__(self, parent=parent)
        self.col_titls = col_titles
        self.data = data
        ...

    def AppendData(self, rows=[], clear=Flase):
        self.data.extend(rows)
        msg = wx.grid.GridTableMessage(self,
                                       wx.grid.GRIDTABLE_NOTIFY_ROWS_DELETED,
                                       0,
                                       len(rows))
        self.ProcessTableMessage(msg)

class MyFrame(wx.Frame):
    def __init(self, parent, title=""):
        wx.Frame.__init__(self, parent=parent, title=title)
        self.grid1 = MyGrid(self)
        self.grid2 = MyGrid(self)
        ...

    def onGridAddCallback(rows, force=False):
        if isinstance(rows, list) and len(rows) > 0:
            self.grid1.AppendData(rows, force) 

当更新gird1的内容时,gird2的成员变量 data 也发生了改变,因此导致异常

可选的解决方案: 避免使用缺省值初始化指针类型成员变量(list, dict …):

class MyFrame(wx.Frame):
    def __init(self, parent, title=""):
        wx.Frame.__init__(self, parent=parent, title=title)
        self.grid1 = MyGrid(self, col_titles=["a", "b", "c"], data=[["1", "2", "3"]])
        self.grid2 = MyGrid(self, col_titles=["a", "b", "c"], data=[["1", "2", "3"]])
        ...

猜你喜欢

转载自blog.csdn.net/a462533587/article/details/80666444