Python中的列表和字典01

由于没有系统的学习python,所以用的时候有时候会走入坑中。例如今天写代码遇到两个问题:

  • 在类的方法中引用了类的成员变量给方法中的变量赋值,而这个成员变量是字典类型,结果发现
    修改方法中的变量时,将类的成员变量值一并修改了。
class A(object):
  r={}
  def __init__(self):
    self.d = {"k":"aaa"}
  def A1(self):
    d2 = self.d
    d2['k'] = 'bbb'
if __name__ == "__main__":
  a = A()
  a.A1()
  print a.d     
'''
输出:{"k":"bbb"}
'''

可以看到,其实我只是修改了,方法中的变量d2,但是成员d的值也被修改了。

  • 以变量形式向列表添加字典,修改列表中元素的值,原字典也改变了
if __name__ == "__main__":
  d={'k':''}
  l = []
  l.append(d)
  l[0]['k'] = 'aaa'
  l.append(d)
  print d
  print l
'''
其实不仅是列表,变量赋值也一样:
d1 = {"k":""}
d2 = d1
d2["k"] = 123
print d1   #{"k",123}
'''
输出:
d={'k':'aaa'}
[{'k':'aaa'},{'k':'aaa'}]

可以看到我只是修改了列表的元素,但是字典的值也变了。
而第二次append(d)后,并没有对l[2]修改,但是由于d变了,
导致添加后的列表l[1]['k']的值已经不是字典d开
始的值了。

  • 通过几组测试,发现列表和字典在python底层,使用地址形式存储,而使用等号相当于只是做
    了浅拷贝,在底层仍然是用的是指针的方式,所以可以使用深拷贝解决问题。

    关于深浅拷贝,简单的来说就是,在有指针的情况下,浅拷贝只是增加了一个指针指向已经存在的内存,而深拷贝就是增加一个指针并且申请一个新的内存,使这个增加的指针指向这个新的内存
    

    demo:

#!/usr/bin/env python
#-*- coding:utf-8 -*-
import copy

class A(object):
  r={}
  def __init__(self):
    self.x = 0
    self.l = []
    self.s = "sss"
    self.d = {"k":"aaa"}

  def A1(self):
    x2 = self.x
    x2 = 2    ##int数 x2 修改后 类的成员self.x不变

  def A3(self):
    s2 = self.s
    s2 = "abc" ##字符串 s2修改后 类的成员self.s不变

  def A2(self):
    l2 = self.l
    l2.append(self.x) ##列表 l2 修改后 类的成员self.s的值-->跟随l2改变
    l2[-1] = 2

  def A4(self):
    d2 = self.d
    r2 = self.r
    d2['k']="bbb"  ##字典 d2 修改后 类的成员self.d的值-->跟随d2改变
    r2['k']="bbb"  ##同上

  def A5(self):
    l2 = []
    x2 = 0
    s2 = ""
    l2.append(x2)   ## 以变量形式向列表添加 int数和字符串
    l2.append(s2)
    print "l2:",l2
    print "x2:", x2
    print "s2:",s2
    l2[0] = '123'   ## 修改列表中对应元素的值
    l2[1]= "bbb"
    print "l2:", l2
    print "x2:", x2  ## 原int数、字符串的值不变
    print "s2:", s2


  def A6(self):
    l2 = []
    l3 = []
    d3 = {'k':''}
    l2.append(d3)  ## 以变量形式向列表添加 列表和字典
    l2.append(l3)
    print "l2:",l2
    print "l3:", l3
    print "d3:",d3
    l2[0]['k'] = 'bbb'  ## 修改列表中对应元素的值
    l2[1].append("bbb")
    #--------------------------------------------------------
    # 这里用append()会使原列表l3变化,但如果是l2[1]=["bbb"]则不会
    # l2.append(l3)相当于将l2的末尾节点指向了l3内存空间,
    # 而l2[1].append("bbb")相当于向这个内存空间存储“bbb”,
    # l2[1] = ['bbb']则是将l2的末尾节点重定向到了['bbb']
    #--------------------------------------------------------
    print "l2:",l2
    print "l3:", l3    ##原列表、字典的值都变化,
    print "d3:",d3

  ### 字典的深拷贝
  def A_dep(self):
    print "self.d",self.d
    print "self.r",self.r
    d_cp = copy.copy(self.d)
    r_dpcp = copy.deepcopy(self.r)
    d_cp['k'] = 'ccc'
    r_dpcp['k'] = 'ccc'
    print "d_cp",d_cp
    print "r_dpcp",r_dpcp
    print "self.d",self.d    ##  使用两种深拷贝,在内存中重新开辟了空间,而不是指针指向的方式
    print "self.r",self.r

    ll = []
    ll2 = []
    ll.append(copy.copy(self.d))
    ll2.append(copy.deepcopy(self.r))
    ll[0]['k'] = "ccc"
    ll2[0]['k'] = "ccc"
    print "ll:",ll
    print "ll2:", ll2
    print "self.d", self.d  ## 以变量形式向列表添加字典,也是一样
    print "self.r", self.r


if __name__ == "__main__":
  a=A()
  print "___测试修改类中的成员:int数___"
  a.A1()
  print "self.x:",a.x
  print "___测试修改类中的成员:字符串___"
  a.A3()
  print "self.s:", a.s
  print "___测试修改类中的成员:列表___"
  a.A2()
  print "slef.l:",a.l
  print "self.x:",a.x
  print "___测试修改类中的成员:字典___"
  a.A4()
  print "self.d",a.d
  print "self.r",a.r
  print "___测试以变量方式向列表添加int数、字符串,然后修改列表中int数、字符串的值,原int数、字符串是否变化___"
  a.A5()
  print "___测试以变量方式向列表添加列表字典,然后修改列表中列表、字典元素的值,原列表、字典是否变化___"
  a.A6()
  print "___测试字典深拷贝____"
  a.A_dep()
'''
/usr/bin/python2.7 /home/zhanglu/PycharmProjects/log_parsing/test_01.py
___测试修改类中的成员:int数___
self.x: 0
___测试修改类中的成员:字符串___
self.s: sss
___测试修改类中的成员:列表___
slef.l: [2]
self.x: 0
___测试修改类中的成员:字典___
self.d {'k': 'bbb'}
self.r {'k': 'bbb'}
___测试以变量方式向列表添加int数、字符串,然后修改列表中int数、字符串的值,原int数、字符串是否变化___
l2: [0, '']
x2: 0
s2: 
l2: ['123', 'bbb']
x2: 0
s2: 
___测试以变量方式向列表添加列表字典,然后修改列表中列表、字典元素的值,原列表、字典是否变化___
l2: [{'k': ''}, []]
l3: []
d3: {'k': ''}
l2: [{'k': 'bbb'}, ['bbb']]
l3: ['bbb']
d3: {'k': 'bbb'}
___测试字典深拷贝____
self.d {'k': 'bbb'}
self.r {'k': 'bbb'}
d_cp {'k': 'ccc'}
r_dpcp {'k': 'ccc'}
self.d {'k': 'bbb'}
self.r {'k': 'bbb'}
ll: [{'k': 'ccc'}]
ll2: [{'k': 'ccc'}]
self.d {'k': 'bbb'}
self.r {'k': 'bbb'}

进程完成,退出码 0
'''

猜你喜欢

转载自blog.csdn.net/frank_abagnale/article/details/79706251