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"]])
        ...
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Python中,成员变量可以在初始化方法中进行初始化初始化方法是一个特殊的方法,用来定义具有哪些属性。在Python中,初始化方法的名称是`__init__`。初始化方法在创建对象时会被直接调用。通过在初始化方法中使用`self.属性名=属性的初始值`的方式来定义属性。 下面是一个示例代码,演示了如何在Python中进行成员变量初始化: ```python class Cat(): def __init__(self): self.name = "Tom" tom = Cat() print(tom.name) # 输出结果为 "Tom" ``` 在上述代码中,`Cat`定义了一个初始化方法`__init__`,在方法内部使用`self.name = "Tom"`给属性`name`赋予了初始值。然后通过创建`Cat`对象`tom`,可以通过`tom.name`来访问和使用这个成员变量。 另外,如果希望在创建对象的同时,就设置对象的属性,可以对初始化方法进行改造。可以把希望设置的属性值定义成初始化方法的参数,在方法内部使用`self.属性 = 形参`的方式来接收外部传递的参数。 下面是一个改造后的示例代码: ```python class Cat(): def __init__(self, name): self.name = name def shout(self): print("%s 喵喵叫" % self.name) tom = Cat("Tom") print(tom.name) # 输出结果为 "Tom" ``` 在上述代码中,`Cat`初始化方法接收一个`name`参数,并通过`self.name = name`来将参数值赋给成员变量`name`。创建`Cat`对象`tom`时,可以通过传递参数`"Tom"`来设置`name`属性的初始值。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值