中国做爰网站,wordpress+park主题,wordpress category_name,长洲网站建设目录
1、赋值 2、赋值的分类——引用赋值、值赋值
1) 不可变对象引用赋值——字符串、数值、元组等
2#xff09;可变对象引用赋值——列表、集合、字典
3#xff09;可变与不可变对象的引用赋值内部分析
4#xff09;在py文件中#xff0c;和作用域有关#xff0c;如…目录
1、赋值 2、赋值的分类——引用赋值、值赋值
1) 不可变对象引用赋值——字符串、数值、元组等
2可变对象引用赋值——列表、集合、字典
3可变与不可变对象的引用赋值内部分析
4在py文件中和作用域有关如在同一个函数中的相同值的变量是相等的即值相等地址也相等
3、深拷贝与浅拷贝
4、循环——序列和非序列的循环中进行元素的修改 1、赋值
# 赋值包含多种赋值方式一般赋值、元组赋值、序列赋值、解包赋值
a long
b,c 1,2
d,e,f,g long
h,*i long
print(a)
print(b)
print(c)
print(d)
print(e)
print(f)
print(g)
print(h)
print(i) long 1 2 l o n g l [o, n, g] 当使用一个*前缀变量的时候表示将序列中对应的元素全部收集到一个列表中(注意总是一个列表)这个列表名为*开头的那个变量名。*号可以出现在任意位置处只要赋值的时候能前后对应位置关系即可。 注意其中的几个关键字序列、对应的元素、列表 序列意味着可以是列表、元组、字符串等等列表意味着只要收集不报错赋值给解包变量的一定是一个列表对应的元素意味着可能收集到0或任意个元素到列表。不管如何收集的结果总是列表只不过可能是空列表或者只有一个元素的列表。 两个注意事项
因为序列解包是根据元素位置来进行赋值的所以不能出现多个解包变量如果将序列直接赋值给单个解包变量时(即没有普通变量)这个解包变量必须放在列表或元组中a,*b,c,*d L # 错误
*a L # 错误
[*a] L # 正确
(*a) L # 正确 2、赋值的分类——引用赋值、值赋值
引用赋值——指的是将内存地址赋值给变量来实现赋值
1) 不可变对象引用赋值——字符串、数值、元组等
a 1000
b a
a 2000
前两行ba是将1000的地址赋值给b即a和b都是指向值1000的内存地址。第三行a2000是对a重新进行赋值因为数值是不可改变的对象因此会先开辟一个内存地址用于存储2000然后将a指向2000
不可变对象变量之间不会互相影响即如果一开始两个变量指向同一个内存地址当其中一个变量的值发生了改变的时候另一个变量不会受到影响
对于不可变对象修改变量的值意味着在内存中要新创建一个数据对象
a 10000
b a
a 20000 a,b
(20000, 10000)
2可变对象引用赋值——列表、集合、字典
对于可变对象比如列表它是在原处修改数据对象的(注意加了双引号)。比如修改列表中的某个元素列表的地址不会变还是原来的那个内存对象所以称之为原处修改。例如
L1 [111,222,333]
L2 L1
L1[1] 2222 L1,L2
([111, 2222, 333], [111, 2222, 333])
L2是通过引用赋值得到的值值为可变对象列表当对L1改变一个列表元素时其列表的地址不会发生改变因此其L2的值也会发生相应的改变
在L1[1]赋值的前后数据对象[111,222,333]的地址一直都没有改变但是这个列表的第二个元素的值已经改变了。因为L1和L2都指向这个列表所以L1修改第二个元素后L2的值也相应地到影响。也就是说L1和L2仍然是同一个列表对象[111,2222,333]。
结论是对于可变对象变量之间是相互影响的。
3可变与不可变对象的引用赋值内部分析
可变对象和不可变对象的赋值形式虽然一样但是修改数据时的过程不一样。
对于不可变对象修改数据是直接在堆内存中新创建一个数据对象。如图 对于可变对象修改这个可变对象中的元素时这个可变对象的地址不会改变所以是原处修改的。但需要注意的是这个被修改的元素可能是不可变对象可能是可变对象如果被修改的元素是不可变对象就会创建一个新数据对象并引用这个新数据对象而原始的那个元素将等待垃圾回收器回收。 L[333,444,555]id(L),id(L[1])
(56583832, 55771984)L[1]4444id(L),id(L[1])
(56583832, 55771952)如图所示 4在py文件中和作用域有关如在同一个函数中的相同值的变量是相等的即值相等地址也相等
3、深拷贝与浅拷贝
1深拷贝
完全创建一个新的数据对象不会受到其他变量的元素值变化的影响
2)浅拷贝只是拷贝了第一层的元素若第一层的元素是可变对象则引用的是可变对象的地址因此还是会受到其他变量的影响
# 引用赋值——只是得到了地址
print(赋值----------------------)
L [1,2,[3,4,5]]
L2 L
print(修改元素前-----------)
print(L)
print(L2)
print(修改元素后-----------)
L[0] 0
print(L)
print(L2) 赋值---------------------- 修改元素前----------- [1, 2, [3, 4, 5]] [1, 2, [3, 4, 5]] 修改元素后----------- [0, 2, [3, 4, 5]] [0, 2, [3, 4, 5]] print(浅拷贝------------------------)print(浅拷贝1------------------------)
# 浅拷贝——只是拷贝了第一层的元素若为不可变元素则会重新为元素创建一个新的数据对象若为可变数据对象则只是拷贝了地址
L [1,2,[3,4,5],6]
L1 L.copy()
print(修改不可变对象的元素前-----------)
print(L)
print(L1)
print(修改不可变对象的元素后-----------)
L[0] 0
print(L)
print(L1)print(浅拷贝1------------------------)
L [1,2,[3,4,5],6]
L1 L.copy()
print(修改可变对象的元素前-----------)
print(L)
print(L1)
print(修改可变对象的元素后-----------)
L[2][0] 0
print(L)
print(L1)print(浅拷贝2------------------------)
L [1,2,[3,4,5]]
L3 L[:]
print(修改元素前-----------)
print(L)
print(L3)
print(修改元素后-----------)
L[0] 0
L[2][0] 0
print(L)
print(L3) 浅拷贝------------------------ 浅拷贝1------------------------ 修改不可变对象的元素前----------- [1, 2, [3, 4, 5], 6] [1, 2, [3, 4, 5], 6] 修改不可变对象的元素后----------- [0, 2, [3, 4, 5], 6] [1, 2, [3, 4, 5], 6] 浅拷贝1------------------------ 修改可变对象的元素前----------- [1, 2, [3, 4, 5], 6] [1, 2, [3, 4, 5], 6] 修改可变对象的元素后----------- [1, 2, [0, 4, 5], 6] [1, 2, [0, 4, 5], 6] 浅拷贝2------------------------ 修改元素前----------- [1, 2, [3, 4, 5]] [1, 2, [3, 4, 5]] 修改元素后----------- [0, 2, [0, 4, 5]] [1, 2, [0, 4, 5]] from copy import deepcopy
print(深拷贝------------------------)
L [1,2,[3,4,5]]
L1 deepcopy(L)
L[0] 0
L[2][0] 0
print(L)
print(L1) 深拷贝------------------------ [0, 2, [0, 4, 5]] [1, 2, [3, 4, 5]] 一般我们使用到的都是浅拷贝
4、循环——序列和非序列的循环中进行元素的修改
https://www.cnblogs.com/f-ck-need-u/p/10129317.html
1列表进行原地修改时L[val1,val2],进行后面的迭代时进行迭代的是修改后的列表因为for是一个迭代器使用的是next即通过索引进行的因此列表原地修改会导致元素出现奇怪的现象
为了避免这种情况我们对列表进行修改时建议生成一个新的列表对象来进行存放
L [a,b,c,d,e]## 原处修改列表新元素f、g也会被迭代
for i in L:if i in de:L [f, g]print(i)## 创建新列表新元素f、g不会被迭代
for i in L:if i in de:L L [f, g]print(i)
这个for迭代器在迭代刚开始的时候先找到L所指向的迭代对象即内存中的[1,2,3,4]。如果迭代过程中如果L变成了一个集合或另一个列表对象for的迭代并不会收到影响。但如果是在原处修改这个列表那么迭代将会收到影响例如新增元素也会被迭代到。
这里通过列表索引来进行元素的遍历和修改即可避免上面的情况
2迭代一个列表迭代过程中删除一个列表元素。
L [a,b,c,d,e]
for i in L:if i in bc:L.remove(i)print(i)print(L)输出的结果将是
b
[a, c, d, e]这个for循环的本意是想删除b、c元素但结果却只删除了b。通过结果可以发现c根本就没有被for迭代。之所以会这样是因为迭代到b的时候满足if条件然后删除了列表中的b元素。正因为删除操作使得列表中b后面的元素整体前移一个位置也就是c元素的索引位置变成了index1而index1的元素已经被for迭代过(即元素b)使得c幸运地逃过了for的迭代。
3迭代的是字典或者集合时虽然两者都是可变序列但是时无序的因此在迭代的过程中是不允许字典或者集合发生改变的否则会报错
D {a:1,b:2,c:3,d:4,e:5}for i in D:if i in bc:del D[i]print(i)print(D)报错
b
Traceback (most recent call last):File g:/pycode/lists.py, line 12, in modulefor i in D:
RuntimeError: dictionary changed size during iterationS {a,b,c,d,e}for i in S:if i in bc:S.remove(i)print(i)print(S)报错
b
Traceback (most recent call last):File g:/pycode/lists.py, line 4, in modulefor i in L:
RuntimeError: Set changed size during iteration若想修改字典的话我们可以复制一份数据对象作为副本然后将副本进行迭代将原来的字典或集合作为修改对象
D {a:1,b:2,c:3,d:4,e:5}for i in D.copy():if i in bc:D.pop(i)print(i)
print(D)S {a,b,c,d,e}for i in S.copy():if i in bc:S.remove(i)print(i)
print(S) 注意在进行可变对象数据对象的迭代与修改时我们只需要将迭代对象和修改对象分开就不会出现上述的错误。