python模板引擎传迭代器_python之旅基础——深浅拷贝、迭代器和生成器

一、变量赋值

在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))

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值