第二章 数据类型和文件操作
变量创建过程
首先,当我们定义了一个变量name = ‘oldboy’的时候,在内存中其实是做了这样一件事:
程序开辟了一块内存空间,将‘oldboy’存储进去,再让变量名name指向‘oldboy’所在的内存地址。如下图所示:
我们可以通过id()方法查看这个变量在内存中的地址
>>> name = "oldboy"
>>> id(name)
4317182304
python 解释器有自动垃圾回收机制,自动隔一段时间把没有跟变量名关联的内存数据回收
name = "wuxiping" name = "Jack" print(id(name)) name = "Alex" name1 = name print(name1) print(id(name),id(name1)) name = "黑姑娘" print(name1) # 因为name1是直接指向Alex,所以name1 没变
身份运算
python 中有很多种数据类型, 查看一个数据的类型的方法是type().
判断一个数据类型是不是str, or int等,可以用身份运算符is
>>> type(name) is str
True
>>>
>>> type(name) is not int
True
# 身份运算 name = "Alex" name1 = "黑姑娘" print(type(name1)) print(type(name1) is str) print(type(name1) is int) # 不能直接说 name1 is str,因为name1 是一个字符串,现在判断的是它是不是一个字符串类型!因此要先拿到它的类型 print(name1 is str) age = 12.32 print(type(age) is not float)
空值None
代表什么都没有的意思,一般用在哪呢? 比如玩游戏,你要初始化一个女朋友, 需要填上姓名、年龄、身高、体重等信息, 这些信息是让玩家填的,在填之前,你要先把变量定义好,那就得存个值 ,这个值用0,1来占位不合适 ,用True,False也不合适 ,用None最合适
>>> name=None
>>> age=None
>>> height=None
>>> weight=None
>>>
>>> name,age,height,weight
(None, None, None, None)
>>>
此时可用is 运算符来判断变量是不是None
>>> if name is None:
... print("你的女朋友还没起名字呢.")
...
你的女朋友还没起名字呢.
其实用==判断也行,但是不符合开发规范
>>> name == None
True
三元运算
显的很NB的代码写法。
# 三元运算 a = 10 b = 5 if a>15: c = a else: c = b print(c) # 或者 d = a if a>15 else b print(d)
d = 值1 if 条件A else 值2
如果条件A成立,就取左边值1,否则就取值2
细讲数据类型----列表
追加,数据会追加到尾部
>>> names
['alex', 'jack']
>>> names.append("rain")
>>> names.append("eva")
>>>
>>> names
['alex', 'jack', 'rain', 'eva']
插入,可插入任何位置
>>> names.insert(2,"黑姑娘")
>>> names
['alex', 'jack', '黑姑娘', 'rain', 'eva']
>>>
合并,可以把另一外列表的值合并进来
>>> n2 = ["狗蛋","绿毛","鸡头"]
>>> names
['alex', 'jack', '黑姑娘', 'rain', 'eva']
>>> names.extend(n2)
>>> names
['alex', 'jack', '黑姑娘', 'rain', 'eva', '狗蛋', '绿毛', '鸡头']
列表嵌套
>>> names.insert(2,[1,2,3])
>>> names
['alex', 'jack', [1, 2, 3], '黑姑娘', 'rain', 'eva', '狗蛋', '绿毛', '鸡头']
>>> names[2][1]
2
删除操作
del 直接删
>>> names
['alex', 'jack', [1, 2, 3], '黑姑娘', 'rain', 'eva', '狗蛋', '绿毛', '鸡头']
>>> del names[2]
>>> names
['alex', 'jack', '黑姑娘', 'rain', 'eva', '狗蛋', '绿毛', '鸡头']
pop 删
>>> names
['alex', 'jack', '黑姑娘', 'rain', 'eva', '狗蛋', '绿毛', '鸡头']
>>> names.pop() #默认删除最后一个元素并返回被删除的值
'鸡头'
>>> names
['alex', 'jack', '黑姑娘', 'rain', 'eva', '狗蛋', '绿毛']
>>> help(names.pop)
>>> names.pop(1) #删除指定元素
'jack'
clear 清空
>>> n2
['狗蛋', '绿毛', '鸡头']
>>> n2.clear()
>>> n2
[]
修改操作
>>> names
['alex', '黑姑娘', 'rain', 'eva', '狗蛋', '绿毛']
>>> names[0] = "金角大王"
>>> names[-1] = "银角大王"
>>> names
['金角大王', '黑姑娘', 'rain', 'eva', '狗蛋', '银角大王']
查操作
>>> names
['金角大王', '黑姑娘', 'rain', 'eva', '狗蛋', '银角大王', 'eva']
>>>
>>> names.index("eva") #返回从左开始匹配到的第一个eva的索引
3
>>> names.count("eva") #返回eva的个数
2
name = ['金角大王', '黑姑娘', 'rain', 'eva', '狗蛋', '银角大王', 'eva'] # 切片,顾头不顾尾 print(name[1:4]) print(name[1:-2]) print(name[1:]) # 可取最后一个数 print(name[:5]) # 倒着切 print(name[-5:-1]) print(name[-5:]) # 步长, 允许跳着取值 print(name[0:-1:1]) print(name[0:-1:2]) print(name[0:-1:3]) # 从右往左走 print(name[-1:-5:-1]) # 步长变成负的即可 print(name[:]) # 都省略,全取 print(name[0:-1:2]) print(name[::2])
# 反转 name = ['金角大王', '黑姑娘', 'rain', 'eva', '狗蛋', '银角大王', 'eva'] n = "银角大王" print(n[::-1]) name.reverse() print(name) # 排序 name.sort() print(name) # 循环列表 for i in name: print(i)
细讲数据类型-元组(大部分和列表相似)
不可修改
索引,切片,等
count,index
注意:元组本身不可变,如果元组中还包含其他可变元素,这些可变元素可以改变
>>> data (99, 88, 77, ['Alex', 'Jack'], 33) >>> data[3][0] = '金角大王' >>> data (99, 88, 77, ['金角大王', 'Jack'], 33)
为啥呢? 因为元组只是存每个元素的内存地址,上面[‘金角大王’, ‘Jack’]这个列表本身的内存地址存在元组里确实不可变,但是这个列表包含的元素的内存地址是存在另外一块空间里的,是可变的。
定义
字符串是一个有序的字符的集合,用于存储和表示基本的文本信息,’ ‘或’’ ‘’或’’’ ‘’’中间包含的内容称之为字符串
反转:将步长变成-1即可
特性:
按照从左到右的顺序定义字符集合,下标从0开始顺序访问,有序
1.可以进行切片操作
2.不可变,字符串是不可变的,不能像列表一样修改其中某个元素,所有对字符串的修改操作其实都是相当于生成了一份新数据。
补充:
1.字符串的单引号和双引号都无法取消特殊字符的含义,如果想让引号内所有字符均取消特殊意义,在引号前面加r,如name=r’l\thf’
字典:
字典是Python语言中唯一的映射类型。
定义:{key1:value1,key2:value2}
特性:
1.key-value结构
2.key必须为不可变数据类型、必须唯一
3.可存放任意多个value、可修改、可以不唯一
4.无序
5.查询速度快,且不受dict的大小影响,至于为何快?我们学完hash再解释。
# coding=utf-8 # 字典:定义:{key1:value1,key2:value2} # info = { # "name":"小猿圈", # "mission": "帮一千万极客高效学编程", # "website": "http://apeland.com"} # print(info.keys()) # 创建操作 # person = {"name": "alex", 'age': 20} # person = dict(name='seven', age=20) # keys = [1,2,3,4,5] # a= {}.fromkeys(keys,100) # print(a) # 增加 # person = {"name": "alex", 'age': 20} # person["job"] = "Teacher" # print(person) # person.setdefault("salary",[1,2,3]) # print(person) # 删除 person = {"name": "alex", 'age': 20} # print(person) # print(person.pop("name")) # 删除指定键key # print(person) # print(person) # del person["name"] # 删除指定键key # print(person) # print(person.clear()) # 清空字典 # 修改操作 # person["name"] = "NAME" # print(person) # 替代原先的value值 # person1 = {"gender":"male"} # print(person.update(person1)) # 将字典person1的键值对添加到字典person中 # print(person) # 查操作 # print(person["name"]) # 返回字典中key对应的值,若key不存在字典中,则报错 # print(person.get("name")) # 返回字典中key对应的值,若key不在字典中,则返回default的值(default默认为None) # print("name" in person) # 若存在则返回True,否则返回False # print(person.keys()) # 返回一个包含字典所有key的列表 # print(person.values()) # 返回一个包含字典所有value的列表 # print(person.items()) # 返回一个包含所有(键,值)元祖的列表 # 循环 # for i in person: # print(i,person[i]) # for i in person.items(): # print(i) # for k,v in person.items(): # print(k,v) # for i in person.keys(): # print(i) for i in person.values(): print(i)
细讲数据类型-集合
定义
1.里面的元素不可变,代表你不能存一个list、dict 在集合里,字符串、数字、元组等不可变类型可以存
2.天生去重,在集合里没办法存重复的元素
3.无序,不像列表一样通过索引来标记在列表中的位置 ,元素是无序的,集合中的元素没有先后之分,如集合{3,4,5}和{3,5,4}算作同一个集合
基于上面的特性,我们可以用集合来干2件事,去重和关系运算
# 创建集合 set 增删查 a = {1,2,3,4,2,'alex',3,'rain','alex'} print(a) a.add(5) print(a) # a.add([1,2,3]) # print(a) a.add((1,2,3)) print(a) # 删除 a.discard(5) # 随机删除 a.pop() # 如果没有该元素就会报错 a.remove()
# 关系运算 s_1024 = {"佩奇","老男孩","海峰","马JJ","老村长","黑姑娘","Alex"} s_pornhub = {"Alex","Egon","Rain","马JJ","Nick","Jack"} print(s_1024 & s_pornhub) # 交集, elements in both set print(s_1024 | s_pornhub) # 并集 or 合集 print(s_1024 - s_pornhub) # 差集 , only in 1024 print(s_pornhub - s_1024) # 差集, only in pornhub print(s_1024 ^ s_pornhub) # 对称差集, 把脚踩2只船的人T出去
print(s_1024.intersection(s_pornhub))
秒懂二进制
字符编码之文字是如何显示的
ASCII码
这张表就是计算机显示各种文字、符号的基石呀
ASCII(American Standard Code for Information Interchange,美国信息交换标准代码)是基于拉丁字母的一套电脑编码系统,主要用于显示现代英语和其他西欧语言。它是现今最通用的单字节编码系统,并等同于国际标准ISO/IEC 646。
在这里,每一位0或者1所占的空间单位为bit(比特),这是计算机中最小的表示单位
每8个bit组成一个字节,这是计算机中最小的存储单位(毕竟你是没有办法存储半个字符的)orz~
bit 位,计算机中最小的表示单位
8bit = 1bytes 字节,最小的存储单位,1bytes缩写为1B
1KB=1024B
1MB=1024KB
1GB=1024MB
1TB=1024GB
1PB=1024TB
1EB=1024PB
1ZB=1024EB
1YB=1024ZB
1BB=1024YB
GBK2312 2个字节代表一个字符
论断句的重要性与必要性:
Unicode标准也在不断发展,但最常用的是用两个字节表示一个字符(如果要用到非常偏僻的字符,就需要4个字节)。现代操作系统和大多数编程语言都直接支持Unicode。
UTF-8
新的问题又出现了:如果统一成Unicode编码,乱码问题从此消失了。但是,如果你写的文本基本上全部是英文的话,用Unicode编码比ASCII编码需要多一倍的存储空间,由于计算机的内存比较大,并且字符串在内容中表示时也不会特别大,所以内容可以使用unicode来处理,但是存储和网络传输时一般数据都会非常多,那么增加1倍将是无法容忍的!!!
为了解决存储和网络传输的问题,出现了Unicode Transformation Format,学术名UTF,即:对unicode字符进行转换,以便于在存储和网络传输时可以节省空间!
- UTF-8: 使用1、2、3、4个字节表示所有字符;优先使用1个字符、无法满足则使增加一个字节,最多4个字节。英文占1个字节、欧洲语系占2个、东亚占3个,其它及特殊字符占4个
- UTF-16: 使用2、4个字节表示所有字符;优先使用2个字节,否则使用4个字节表示。
- UTF-32: 使用4个字节表示所有字符;
总结:UTF 是为unicode编码 设计 的一种 在存储 和传输时节省空间的编码方案。
如果你要传输的文本包含大量英文字符,用UTF-8编码就能节省空间:
哈希特性
不可逆:在具备编码功能的同时,哈希算法也作为一种加密算法存在。即,你无法通过分析哈希值计算出源文件的样子,换句话说:你不可能通过观察香肠的纹理推测出猪原来的样子。
计算极快:20G高清电影和一个5K文本文件复杂度相同,计算量都极小,可以在0.1秒内得出结果。也就是说,不管猪有多肥,骨头多硬,做成香肠都只要眨眨眼的时间,
哈希的用途
哈希算法的不可逆特性使其在以下领域使用广泛
1.密码,我们日常使用的各种电子密码本质上都是基于hash的,你不用担心支付宝的工作人员会把你的密码泄漏给第三方,因为你的登录密码是先经过 hash+各种复杂算法得出密文后 再存进支付宝的数据库里的
2.文件完整性校验,通过对文件进行hash,得出一段hash值 ,这样文件内容以后被修改了,hash值就会变。 MD5 Hash算法的”数字指纹”特性,使它成为应用最广泛的一种文件完整性校验和(Checksum)算法,不少Unix系统有提供计算md5 checksum的命令。
3.数字签名,数字签名技术是将摘要信息用发送者的私钥加密,与原文一起传送给接收者。接收者只有用发送者的公钥才能解密被加密的摘要信息,然后用HASH函数对收到的原文产生一个摘要信息,与解密的摘要信息对比。如果相同,则说明收到的信息是完整的,在传输过程中没有被修改,否则说明信息被修改过,因此数字签名能够验证信息的完整性。
此外,hash算法在区块链领域也使用广泛。
md5加密算法
基于hash的数据类型有哪些?
Python 中基于hash的2个数据类型是dict and set , 之前说dict查询速度快,为何快? 说set天生去重,怎么做到的?其实都是利用了hash的特性,我们下面来剖析
用Python操作文件
f=open(filename) # 打开文件
f.write("我是野生程序员") # 写操作
f.read() #读操作
f.close() #保存并关闭
操作模式
- r 只读模式
- w 创建模式,若文件已存在,则覆盖旧文件
- a 追加模式,新数据会写到文件末尾