赞
踩
一、变量赋值
在python中,具体的数据为主体,而变量名其实是贴在具体数据的一个标签,变量名指向的是存放数据的内存地址。(变量名好比门牌号,存放数据的内存好比是房间)
a = 1 #给整数1,贴上了一个a的标签
b = a #将整数1的内存地址赋值给b,其实就是给整数1又贴上了b的标签
print("a的内存地址%s,b的内存地址%s,a的值为%s,b的值为%s" % (id(a), id(b), a, b))
#所以看出,a和b的内存地址完全一样,变量也一样
b = 2 #在内存中又创建了一个整数2,标签b又指向了整数2的内存地址
print("a的内存地址%s,b的内存地址%s,a的值为%s,b的值为%s" % (id(a), id(b), a, b))
#此时可以看出,由于内存中整数1和整数2内存地址不同,赋值给b,不会影响标签a的指向
a的内存地址1945988112,b的内存地址1945988112,a的值为1,b的值为1
a的内存地址1945988112,b的内存地址1945988144,a的值为1,b的值为2
二、浅拷贝
首先说明,list1 = list2,这样的赋值操作,就是给list2指向的内存地址又贴了一个list1的标签,所以,在这种情况下,无论修改list1,还是list2,都会修改同一个内存地址中的列表数据。
与赋值不同,拷贝是指在内存中开辟新的内存空间给新的数据,只是拷贝得到的数据和原数据一样,但内存地址不一样。
list1 = [1,2,3,4]
list2 = list1.copy()
print("list1的内存地址%s,list2的内存地址%s,list1==%s,list2==%s" % (id(list1), id(list2), list1, list2))
list1的内存地址2636523329224,list2的内存地址2636522465608,list1==[1, 2, 3, 4],list2==[1, 2, 3, 4]
列表list的方法copy()和切片都是属于浅拷贝。
浅拷贝是指:对于列表中有嵌套列表的情况来说,外层的列表数据是拷贝的,但里面的列表和原列表中的内存地址相同。
list1 = [1, 2, 3, [4,5,6]] #list1列表中的第四个元素是个列表
list2 = list1.copy() #对list1进行浅拷贝,赋值给list2
list2[0] = 8 #对list2的第一个元素进行修改
print("list1[0]的内存地址:%s,list2[0]的内存地址%s" % (id(list1[0]), id(list2[0])))
print("list1[0]==%s,list2[0]==%s" % (list1[0], list2[0])) #对list2的第一层元素进行操作,不会影响list1原来的数据
list2[-1][1] = 10
print("list1[-1]的内存地址:%s,list2[-1]的内存地址%s" % (id(list1[-1]), id(list2[-1])))
print("list1[-1]==%s,list2[-1]==%s" % (list1[-1], list2[-1])) #对list2的第四个元素列表中的数据进行修改,list1中同样位置的数据也会改变
list1[0]的内存地址:1945988112,list2[0]的内存地址1945988336
list1[0]==1,list2[0]==8
list1[-1]的内存地址:1578519582408,list2[-1]的内存地址1578519582408
list1[-1]==[4, 10, 6],list2[-1]==[4, 10, 6]
三、深拷贝
深拷贝就是把所有的数据都完全备份,获得一个完全独立的数据
import copy
list1 = [1, 2, 3, [4,5,6]]
list2 = copy.deepcopy(list1) #对list1进行深拷贝
list2[-1][1] = 10
print("list1==%s,list2==%s" % (list1,list2)) #list1和list2完全独立
list1==[1, 2, 3, [4, 5, 6]],list2==[1, 2, 3, [4, 10, 6]]
注:copy模块中的copy.copy()就是浅拷贝
四、迭代器
迭代器协议:对象必须提供一个next()方法,执行该方法要么返回迭代中的下一项,要么就引起一个StopIteration异常,以终止迭代(只能往后,不能前退)。
根据迭代器协议,可以看出字符串、列表、元祖、集合、字典和文件对象,都不算是真正的可迭代对象,因为他们本身不提供next()方法。但是当它们通过for循环,它们会调用自身的__iter__()方法,使得它们都变成了可迭代对象。
list1 = [i for i in range(5)] #利用列表解析式得到[0,1,2,3,4]
list1_iter = list1.__iter__() #调用迭代器的__iter__()方法,得到迭代器
print(next(list1_iter)) #调用内置函数next(),输出0
print(list1_iter.__next__()) #调用迭代器的__next__()方法,输出1二者效果相同,
迭代器就是可迭代对象。在调用for循环的时候,python自动将列表等数据类型变成迭代器。所以,从广义上我们也把列表成为可迭代对象。
用while循环模拟for循环:
list1 = [1,2,3,4,5]
list1_iter = list1.__iter__()
while True:
try:
print(list1_iter.__next__())
except StopIteration:
print("迭代终止")
break
五、生成器
生成器就是自动实现了迭代器协议,即它不需要调用__iter__()方法。
生成器有两种形式:
1、生成器函数:在函数定义过程中,用yeild语句代替return。
def func():
yield 1
yield 2
yield 3
a = func()
print(a) #
print(list(a)) #[[1, 2, 3]]
2、生成器表达式:
gen1 = (i for i in range(10) if i%2 == 0)
print(gen1) # at 0x00000145C79263B8>
print(next(gen1))
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。