deepcopy

小说:皇冠现金网诈骗作者:开密丁更新时间:2018-10-17字数:42163

deepcopy


 

本文适应人群:C# or Python3 基础巩固

代码裤子: https://github.com/lotapp/BaseCode

在线编程: https://mybinder.org/v2/gh/lotapp/BaseCode/master

在线预览:http://github.lesschina.com/python/base/ext/基础衍生.html

马上快期末考试了,老师蜜月也回来了,于是有了一场跨季度的复习讲课了:

1.Python基础语法扩展¶

1.1.if 判断条件相关¶

None、""、0、[]、{} ==> 假

1、" "、[None,""]、{"":None} ==> 真

小明可高兴了,前几天被打击的面目全非,这几天老师回来了,又可以大发神威了,于是抢先提交demo:

In [1]:
# None
if None:
    print(True)
else:
    print(False)
 
False
In [2]:
# 0为False
if 0:
    print(True)
else:
    print(False)
 
False
In [3]:
# 空字符串
if "":
    print(True)
else:
    print(False)
 
False
In [4]:
# 空列表为False
if []:
    print(True)
else:
    print(False)
 
False
In [5]:
# 空字典为False
if {}:
    print(True)
else:
    print(False)
 
False
In [6]:
# 1为True
if 1:
    print(True)
else:
    print(False)
 
True
In [7]:
# 含空格
if " ":
    print(True)
else:
    print(False)
 
True
In [8]:
if [None,""]:
    print(True)
else:
    print(False)
 
True
In [9]:
if {"":None}:
    print(True)
else:
    print(False)
 
True
 

老师微带笑容的看了小明一眼,然后接着讲if的扩展

1.2.三元表达符¶

eg:max = a if a > b else b

In [10]:
a, b = 1, 2

max = a if a > b else b

print(max)
 
2
In [11]:
a, b, c = 1, 3, 2

max = a if a > b else b
max = max if max > c else c

print(max)
 
3
In [12]:
# 上面的那个还有一种简写(不推荐)
a, b, c = 1, 3, 2

max = (a if a > b else b) if (a if a > b else b) > c else c

print(max)
 
3
 

1.2.字符串和编码¶

Python3.x版本中,字符串是以Unicode编码的

对于单个字符的编码,Python提供了ord()函数获取字符的整数表示,chr()函数把编码转换为对应的字符

小潘对这块有所研究,把小明按在桌上然后抢先提交demo:

In [13]:
ord("D")
Out[13]:
68
In [14]:
ord("毒")
Out[14]:
27602
In [15]:
chr(68)
Out[15]:
"D"
In [16]:
chr(27602)
Out[16]:
"毒"
In [17]:
print(ord("A"))
print(ord("Z"))

print(ord("a"))
print(ord("z"))
 
65
90
97
122
 

老师补充讲解道:

编码:encode() 解码:decode()

url相关的可以用:

urllib.parse.quote() and urllib.parse.unquote()

urllib.parse.urlencode() 可以直接对一个key-value进行url编码

In [18]:
# encode() and decode()
name="毒逆天"

name_encode=name.encode("utf-8")

print(name_encode)

print(name_encode.decode("utf-8"))
 
b"xe6xafx92xe9x80x86xe5xa4xa9"
毒逆天
In [19]:
# 需要导入urlib.parse

import urllib.parse
In [20]:
test_str="淡定"

# 对字符串进行url编码和解码
test_str_enode = urllib.parse.quote(test_str)

print(test_str_enode)

# urllib.parse.quote() 解码
print(urllib.parse.unquote(test_str_enode))
 
%E6%B7%A1%E5%AE%9A
淡定
In [21]:
# urlencode 可以直接对一个key-value进行编码

test_dict={"name":"毒逆天","age":23}

encode_str = urllib.parse.urlencode(test_dict)

print(encode_str)
print(urllib.parse.unquote(encode_str))
 
name=%E6%AF%92%E9%80%86%E5%A4%A9&age=23
name=毒逆天&age=23
 

1.3.值判断和地址判断¶

小明不乐意了,你个小潘总是抢我的风头,看完标题就刷刷的在黑板上写下了如下知识点:

is 是比较两个引用是否指向了同一个对象id()得到的地址一样则相同)

== 是比较两个对象的值是否相等

在之前讲Dict的时候提了一下可变和不可变类型:https://www.cnblogs.com/dotnetcrazy/p/9155310.html#5.2.增加和修改

Func里面又系统的说了一下:https://www.cnblogs.com/dotnetcrazy/p/9175950.html#4.5.可变类型和不可变类型

对于可变不可变系列就不去复述了,下面再来几个案例看看 值判断地址判断的概念

In [22]:
################ 可变类型 ################ 
In [23]:
a=[1,2,3]
b=[1,2,3]

# id不一样,那is肯定不一样了
print(id(a))
print(id(b))
 
139727165899464
139727165725256
In [24]:
# a和b是否指向同一个地址
a is b
Out[24]:
False
In [25]:
# a和b的值是否相同
a == b
Out[25]:
True
In [26]:
################ 开始变化了 ################ 
In [27]:
# 让a指向b的地址
a=b

# a和b的id一样了
print(id(a))
print(id(b))
 
139727165725256
139727165725256
In [28]:
# a和b是否指向同一个地址
a is b
Out[28]:
True
In [29]:
# a和b的值是否相同
a == b
Out[29]:
True
In [30]:
################ 不可变类型 ################ 
In [31]:
a=1
b=1

# id一样
print(id(a))
print(id(b))
 
94592578394656
94592578394656
In [32]:
a is b
Out[32]:
True
In [33]:
a == b
Out[33]:
True
In [34]:
# 但是你要注意,不是所有不可变类型都这样的

f1=1.2
f2=1.2

# 声明两个相同值的浮点型变量,查看它们的id,发现它们并不是指向同个内存地址(这点和int类型不同)
print(id(f1))
print(id(f2))
 
139727217917024
139727217917096
In [35]:
# 这个就不一样了
# 这方面涉及Python内存管理机制,Python对int类型和较短的字符串进行了缓存
# 无论声明多少个值相同的变量,实际上都指向同个内存地址,其他的就没这福利咯~

f1 is f2
Out[35]:
False
In [36]:
f1 == f2
Out[36]:
True
 

2.Python总结之for系列¶

老师徐徐道来:“之前说for总是零零散散的,现在基础都讲完了,来个小汇总:”

2.1.Base¶

能够被for循环遍历的,就是可迭代的

For基础系:https://www.cnblogs.com/dotnetcrazy/p/9102030.html#9.1.Python

In [37]:
# 类似于for(int i=0;i<5;i++)

for i in range(5):
    print(i)
    
 
0
1
2
3
4
In [38]:
#while循环一般通过数值是否满足来确定循环的条件
#for循环一般是对能保存多个数据的变量,进行遍历

name="https://pan.baidu.com/s/1weaF2DGsgDzAcniRzNqfyQ#mmd"

for i in name:
    if i=="#":
        break
    print(i,end="")#另一种写法:print("%s"%i,end="")
print("
 end ...")
 
https://pan.baidu.com/s/1weaF2DGsgDzAcniRzNqfyQ
 end ...
In [39]:
# 你期望的结果是:i = 5

for i in range(10):
    if i == 5:
        print("i = %d" % i)
else:
    print("没有找到")
 
i = 5
没有找到
In [40]:
# 当迭代的对象迭代完并为空时,位于else的子句将执行
# 而如果在for循环中含有break时则直接终止循环,并不会执行else子句
# 正确写法如下:

for i in range(10):
    if i == 5:
        print("i = %d" % i)
        break
else:
    print("没有找到")
 
i = 5
In [41]:
# 遍历一个字典

test_dict={"Name":"小明","Age":23}

for k,v in test_dict.items():
    print("key:%s,value:%s"%(k,v))
 
key:Name,value:小明
key:Age,value:23
 

2.2.列表生成式¶

如果下面知识点还不熟悉的,看看之前讲的~列表生成式:https://www.cnblogs.com/dotnetcrazy/p/9155310.html#1.9.列表生成式

简写list(range(1, 11)) 全写[x for x in range(1,11)]

In [42]:
list(range(1, 11))
Out[42]:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
In [43]:
[x for x in range(1,11)]
Out[43]:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
In [44]:
# 1~10的平方列表
[x*x for x in range(1,11)]
Out[44]:
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
In [45]:
# 1~10之间的偶数
[x for x in range(1, 11) if x % 2 == 0]
Out[45]:
[2, 4, 6, 8, 10]
In [46]:
# 数学里面的全排列
[x + y for x in "ABC" for y in "AB"]
Out[46]:
["AA", "AB", "BA", "BB", "CA", "CB"]
In [47]:
# 数学里面的坐标轴
[(x,y) for x in range(1,5) for y in range(1,4)]
Out[47]:
[(1, 1),
 (1, 2),
 (1, 3),
 (2, 1),
 (2, 2),
 (2, 3),
 (3, 1),
 (3, 2),
 (3, 3),
 (4, 1),
 (4, 2),
 (4, 3)]
In [48]:
# (x,y,z) 一般三个嵌套就上天了
[(x,y,z) for x in range(1,5) for y in range(1,4) for z in range(1,3)]
Out[48]:
[(1, 1, 1),
 (1, 1, 2),
 (1, 2, 1),
 (1, 2, 2),
 (1, 3, 1),
 (1, 3, 2),
 (2, 1, 1),
 (2, 1, 2),
 (2, 2, 1),
 (2, 2, 2),
 (2, 3, 1),
 (2, 3, 2),
 (3, 1, 1),
 (3, 1, 2),
 (3, 2, 1),
 (3, 2, 2),
 (3, 3, 1),
 (3, 3, 2),
 (4, 1, 1),
 (4, 1, 2),
 (4, 2, 1),
 (4, 2, 2),
 (4, 3, 1),
 (4, 3, 2)]
 

2.3.扩展¶

如果要对list实现类似C#或者java那样的下标循环怎么办?

这块小明又有预习,于是在提交Code的同时大声说道:

Python内置的enumerate函数可以把一个list变成索引-元素对,这样就可以在for循环中同时迭代索引和元素本身

In [49]:
for i, item in enumerate(["A", "B", "C"]):
    print(i, item)
 
0 A
1 B
2 C
 

3.Python中赋值、浅拷贝、深拷贝¶

看到标题小明和小潘就楞了,老师当时没讲解啊,然后两个人眼巴巴的看着老师讲解:

官方文档:https://docs.python.org/3/library/copy.html

3.1.赋值¶

通过=来实现,就是把地址拷贝了一份,比如 a = b

In [50]:
a=[1,2,2]
b = a

print(id(a))
print(id(b))
 
139727165518536
139727165518536
In [51]:
# 再验证

a.append(3)

# 都增加了一个3,说明的确指向同一个内存地址
print(a)
print(b)
 
[1, 2, 2, 3]
[1, 2, 2, 3]
 

3.2.深拷贝deepcopy¶

导入copy模块,调用deepcopy方法

如果有嵌套引用的情况,直接递归拷贝

In [52]:
import copy

a=[1,2,2]
In [53]:
b=copy.deepcopy(a)

# 指向了不同的内存地址
print(id(a))
print(id(b))
 
139727165899080
139727165900488
In [54]:
# 再验证一下

a.append(3)

# b不变,说明的确指向不同的内存地址
print(a)
print(b)
 
[1, 2, 2, 3]
[1, 2, 2]
In [55]:
################ 开始变化了 ################ 
In [56]:
# 之前讲了嵌套列表,我们来验证一下

a=[1,2,2]
b=[1,2,3,a]

c=copy.deepcopy(b)

# 发现地址都不一样
print(id(b))
print(id(c))
print(id(b[3]))
print(id(c[3]))
 
139727166586248
139727165899080
139727165725256
139727165899464
In [57]:
# 直观的验证一下

a.append(666)

# 深拷贝的确是深拷贝
print(b)
print(c)
 
[1, 2, 3, [1, 2, 2, 666]]
[1, 2, 3, [1, 2, 2]]
 

3.3.浅拷贝copy¶

copy只是简单拷贝,如果拷贝内容里面还有引用之类的,他是不管的

In [58]:
import copy

a=[1,2,2]
In [59]:
b=copy.copy(a)

# 指向了不同的内存地址
print(id(a))
print(id(b))
 
139727165902088
139727165850952
In [60]:
################ 开始变化了 ################ 
In [61]:
# 之前讲了嵌套列表,我们来验证一下

a=[1,2,2]
b=[1,2,3,a]

c=copy.copy(b)

# 第一层地址不一样
print(id(b))
print(id(c))
 
139727165519432
139727165902088