python基础第6天(day18) 字符编码 ,基础复习

 字符编码 ,基础复习

参考:http://www.cnblogs.com/yuanchenqi/articles/5956943.html

ASCII码:127个数字: 7个比特位 ----->美国 最高位0一个字节,8位
扩展ASCII码:256个数字: 8个比特位 ------>拉丁 
中文扩展ASCII码(GB2312): 几千个状态 ------>中国   两个字节的最高位都是1才表示中位
中文扩展ASCII码(GBK): 两万个状态 ------>中国        两个字节,最高位的那一个位是1就认为其余15位也是表示中文


Uicode(明文:二进制数字) 就比如直接从记事本输入字在内存中就是unicode unicode 才对应明文 -----六万多个状态 -----全世界

Utf8(二进制对应二进制)
打开一个文本的过程:文本编辑器把二进制文字,解码成Unicode在内存,unicode对应明文显示,utf8是不直接对对应明文的,

python解释器是什么?
把一堆程序(程序在磁盘都是二进制的形式),解码,再编码,,然后按照python的语法来执行
跟文本编辑器是一样的,-*-coding-utf8 -*-就是告诉解析器,
我默认都是以utf8解码的

unicode字符编码一定是有个u字

python2.x:(2解释器默认是用ASCII解码)两种数据类型
1 str(就是起的一个名字):bytes数据(存的真正数据)
2 unicode(就是起的一个名字):unicode编码后二进制数据(存的真正数据)
内存中永远存的都是Unicode是不对的
python3.x:(3解释器默认是按utf-8来解释)

1 str(就是起的一个名字):unicode(存储的类型)
2 bytes(就是起的一个名字):bytes(存储的类型)

python3最大的特点把字节类,和字符类,清楚的分开,如果混用直接报错

注意点: 1 unicode,utf8,GBK都是编码规则。
2 为什么内存存储unicode。
3 程序执行前和执行后两个状态



编码:明文《-----》二进制数字

 

#coding:utf8


#python2.x

# a=1
#
# s="苑昊"
# s2=u"李杰"
#
#
#
#
# # print repr(s)
# # print repr(s2)
#
# print type(s.decode("utf8"))
# print s.decode("gbk")
#
# print type(s2.encode("utf8"))
# print type(s2.encode("gbk"))
#
# print s2.encode("utf8")
# print s2.encode("gbk")

 

# print(type("hello"+u"world"))

#python3.x-----------------------

#
#
# s="李杰"
#
# s2=b"hello"

 

# print(type(s))
# print(type(s.encode("GBk")))
#
# print(type(s2))
# print(type(s2.decode("utf8")))

# print(s.decode("utf8"))

# print(type(b"hello"+b"world"))
#
# print(b"hello".swapcase())

 

##################################################################################

一、字符编码
什么是编码?
基本概念很简单。首先,我们从一段信息即消息说起,消息以人类可以理解、易懂的表示存在。我打算将这种表示称为“明文”(plain text)。对于说英语的人,纸张上打印的或屏幕上显示的英文单词都算作明文。
其次,我们需要能将明文表示的消息转成另外某种表示,我们还需要能将编码文本转回成明文。从明文到编码文本的转换称为“编码”,从编码文本又转回成明文则为“解码”。
记住一句话:计算机中的所有数据,不论是文字、图片、视频、还是音频文件,本质上最终都是按照类似 01010101 的二进制存储的。
 
unicode 是一种二进制编码方式
unicode 它能把目前世界上所有能描述出来的字符与二进制数字对应的一张表,UNICODE是用两个字节来表示为一个字符,它总共可以组合出65535不同的字符,这足以覆盖世界上所有符号(包括甲骨文)
UTF-8(8-bit Unicode Transformation Format)可变长编码,是一种针对Unicode的可变长度字符编码,它可以使用1~4个字节表示一个符号,根据不同的符号而变化字节长度,当字符在ASCII码的范围时,就用一个字节表示,所以是兼容ASCII编码的。 这样显著的好处是,虽然在我们内存中的数据都是unicode,但当数据要保存到磁盘或者用于网络传输时,直接使用unicode就远不如utf8省空间啦! 这也是为什么utf8是我们的推荐编码方式。
 
Unicode与utf8的关系: 一言以蔽之:Unicode是内存编码表示方案(是规范),而UTF是如何保存和传输。Unicode的方案(是实现)这也是UTF与Unicode的区别。
 
ASCII码:127个数字,7个比特位 --->美国
扩展ASCII码:128个数字,8个比特位 --->拉丁文
中文扩展ASCII码:两个字节而且都高于7位拼凑的位(规定一个小于127的字符的意
义与原来相同,但两个大于127的字符连在一起时,就表示一个汉字,前面的一个字节(他称之为高字节)从0xA1用到0xF7,后面一个字节),对应几千个状态 GB2312
中文扩展ASCII码:对应三万左右个状态 GBK
Unicode:两个字节,对应有六万多状态 --->全世界
Unicode是把明文的符号对应编码成二进制数字
UTF-8:可变长的编码
把unicode对应的二进制数再转换成一个二进制数
只有unicode才能对应明文,打开文件首先是从utf8编码 转成 unicode 然后再由unicode 转成明文显示。
 
当存的时候以utf-8保存,而打开的时候以GB2312打开就会有乱码。
 
二、python解释器
# -*- coding:utf-8 -*- 告诉解释器,此文件 我是以utf8 进行编码存盘的,解码的时候要以这个进行解码,如果在python2.7版本中 你不告诉解释器 编码方式,那么它默认以ASCII来解码。
python 2.x 在解释过程中遇到的字符串有两种形式:
(1)str 型:bytes 数据
如:s1 = "解释器" 这里从磁盘读到内存首先是存的unicode数据然后执行的时候根据语法的定义 会变成一个字节(bytes)数据了(所有的字节数据都是通过unicode编码而来的)
(2)unicode 型:unicode 编码后的二进制数
如:s2 = u”解释器“
 
 
python 2.x
下面的是一个程序执行过程怎么把一个个字符串存成什么样的编码(这和文本的存储是不一样的过程)s 是一个bytes类型,s2存的是一个unicode类型
 
无论是utf8还是gbk都只是一种编码规则,一种把unicode数据编码成字节数据的规则,所以utf8编码的字节一定要用utf8的规则解码,否则就会出现乱码或者报错的情况。
 
#coding:utf8
print '苑昊' # 苑昊 #str/bytes类型
print repr('苑昊')#'\xe8\x8b\x91\xe6\x98\x8a'
print (u"hello"+"yuan")
 
#print (u'苑昊'+'最帅') #UnicodeDecodeError: 'ascii' codec can't decode byte 0xe6
# in position 0: ordinal not in range(128)
Python 2 悄悄掩盖掉了 byte 到 unicode 的转换,只要数据全部是 ASCII 的话,所有的转换都是正确的,一旦一个非 ASCII 字符偷偷进入你的程序,那么默认的解码将会失效,从而造成 UnicodeDecodeError 的错误。py2编码让程序在处理 ASCII 的时候更加简单。你付出的代价就是在处理非 ASCII 的时候将会失败。
 
 
 
python 3.x
(1)str类型 存的是unicode编码的的二进制数据
(2)bytes类型 存的是bytes的数据
 
python3.x中unicode就是用来显示用的,bytes就是用来存储和传输用的
 
python 3 编码方面最大的改进:
python 3 把字节类型和字符类型清晰的分开了,如果混用会报错。
 
如图:
 
注意点:
1、unicode、utf8、GBK 都是编码规则;
2、为什么内存存储unicode
3、程序解释前(解释器怎么把程序文件放到内存的,这就是靠python解释器根据python代码中声明的# -*- coding:utf-8 -*- 来进行解码成unicode然后放到内存中)程序执行中(拿到unicode的代码后怎么执行的)
***************************************************************************************************
encode和decode都是文件执行过程中才会进行的。只有执行的时候才会把字符串存成字节的概念。
 
编码:
明文 <-----------> 二进制数字
 
当我把文件编码改成gbk,然后开始写代码存盘,那么存硬盘上的是gbk编码,此时如果要执行代码,那么python2或者python3解释器都有自己默认的解码方式python2默认的是ASCII码,而python3默认的是uft8,存盘编码是gbk,而解码用ascii或uft8,因此是无法解码的,不过加上# -*- coding:gbk -*- 告诉解释器用这个编码来解码,那就能正常执行了。
 
文件从磁盘到内存的编码
抛开执行执行程序,请问大家,文本编辑器大家都是用过吧,如果不懂是什么,那么word总用过吧,ok,当我们在word上编辑文字的时候,不管是中文还是英文,计算机都是不认识的,那么在保存之前数据是通过什么形式存在内存的呢?yes,就是unicode数据,为什么要存unicode数据,这是因为它的名字最牛叉:万国码!解释起来就是无论英文,中文,日文,拉丁文,世界上的任何字符它都有唯一编码对应,所以兼容性是最好的。
 
好,那当我们把数据存到磁盘上又是什么格式?
答案:是通过某种编码方式编码的bytes字节串。比如utf8 ---一种可变长编码,很好的节省了空间;当然还有历史产物的gbk编码等等。于是,在我们的文本编辑器软件都有默认的保存文件的编码方式,比如utf8,比如gbk。当我们点击保存的时候,这些编辑软件已经"默默地"帮我们做了编码工作。
那当我们再打开这个文件时,软件又默默地给我们做了解码的工作,将数据再解码成unicode,然后就可以呈现明文给用户了!
所以,unicode是离用户更近的数据,bytes是离计算机更近的数据。*********************
说了这么多,和我们程序执行有什么关系呢?
先明确一个概念:python解释器本身就是一个软件,一个类似于文本编辑器一样的软件!
 
现在让我们一起还原一个py文件从创建到执行的编码过程:
打开pycharm,创建hello.py文件,写入
ret=1+1 s='苑昊' print(s)
当我们保存的的时候,hello.py文件就以pycharm默认的编码方式保存到了磁盘;关闭文件后再打开,pycharm就再以默认的编码方式打开该文件并读到的内容进行解码,转成unicode到内存我们就看到了我们的明文;
而如果我们点击pycharm运行按钮或者在命令行运行该文件时,python解释器这个软件就会被调用,打开文件,然后解码存在磁盘上的bytes数据成unicode数据,这个过程和编辑器是一样的,不同的是解释器会再将这些unicode数据翻译成C代码再转成二进制的数据流,最后通过控制操作系统调用cpu来执行这些二进制数据,整个过程才算结束。
那么问题来了,我们的文本编辑器有自己默认的编码解码方式,我们的解释器有吗?
当然有啦,python2默认ASCII码,python3默认的utf8,可以通过如下方式查询。
 
import sys
print(sys.getdefaultencoding())
 
#coding:utf8
是的,这就是因为如果python2解释器去执行一个utf8编码的文件,就会以默认地ASCII去解码utf8,一旦程序中有中文,自然就解码错误了,所以我们在文件开头位置声明 #coding:utf8,其实就是告诉解释器,你不要以默认的编码方式去解码这个文件,而是以utf8来解码。而python3的解释器因为默认utf8编码,所以就方便很多了。
 
 
***************************************cmd下的乱码问题****************************************
#coding:utf8
print ('苑昊')
 
文件保存时的编码也为utf8。
思考:为什么在IDE下用2或3执行都没问题,在cmd.exe下3正确,2乱码呢?
我们在win下的终端即cmd.exe去执行,大家注意,cmd.exe本身也一个软件;当我们python2 hello.py时,python2解释器(默认ASCII编码)去按声明的utf8编码文件,而文件又是utf8保存的,所以没问题;问题出在当我们print'苑昊'时,解释器这边正常执行,也不会报错,只是print的内容会传递给cmd.exe用来显示,而在py2里这个内容就是utf8编码的字节数据,可这个软件默认的编码解码方式是GBK,所以cmd.exe用GBK的解码方式去解码utf8自然会乱码。
python3正确的原因是传递给cmd的是unicode数据,cmd.exe可以识别内容,所以显示没问题。
明白原理了,修改就有很多方式,比如:
print (u'苑昊')
改成这样后,cmd下用2也不会有问题了。
 
 
python2 用utf8编码来解码utf8保存的文件,
print ('苑昊') #str类型 存的是bytes类型 也就是utf8编码的二进制数据,然后打印到cmd.exe终端,而cmd.exe 是gbk的编码,要用gbk的方式解码utf8的会出现乱码
 
python3 用utf8编码来解码utf8保存的文件,
print ('苑昊') #str类型 存的是unicode编码的二进制数据,然后cmd.exe默认是gbk因此可以正确显示
***************************************************************************************************
三、基础总结
编译型语言是一次编译多次执行。
解释型语言逐行解释执行。
 
(1)变量
只要是对象,它就能通过 对象.方法() 对对象进行操作
a = 1 通过a引用了1这个数据对象,a引用了变量1
 
变量的命名规则:
1、不能以数字、特殊符号开头
2、不能以关键字命名
 
(2)运算符
算数运算符:+-*/
赋值运算符:=,+=,-=,*=,/=
比较运算符:==,>,<,>=,<=,!= (得到的是一个bool值)
逻辑运算符:and or not
关系运算符:in,not in
如:2 in [1,2,3] #这其实表示2和这个列表中的对象2 引用的是否是同一个对象
位运算符
 
数据类型
整型(在python中只有一个数据类型那就是长整型)
python3 中无论多大数字,只要打印它的数据类型就是int,这个int在python3.x中叫长整型。
 
数据类型按可变与否划分成:
可变数据类型:列表、字典、集合
不可变数据类型:整型、元组、字符串 (一旦创建就不能再修改了)
 
浮点型:科学计数法 0.000123 1.23e-4
float
double
布尔值:
True 1
False 0
 
字符串(String):
print (r"\test.dfdf") # r表示不是转义的普通符号
 
切片:对于序列都可以切片
strip:把字符串开头和结尾的空格和换行符\n去掉
字符串的拼接:
s = "hello"+"world"+"I"+"am"+"python" #这要开辟n块内存地址,很消耗资源
一般推荐使用join join() 括号里面放列表
print (" ".join(["1","2","3"])) #join是只要申请一次内存就ok了
 
split("l",1) #1表示只分割一次
find 没找到会返回 -1 并不会报错
index 类似find,不过找不到会报错的
"hello world".replace("world","python") #把world替换成python
格式化输出
%s 字符串
%d 整型
%f 浮点型
 
format的方式格式化输出
print ("hello {0},his age is {1}".format("alex",20))
print ("hello {name},his age is {age}".format(name="wusir",age=20)) #推荐用这种
print ("hello {name},his age is {age}".format_map({"name":"egon","age":20})) #format_map() 括号里面接的是一个字典
 
 
isnumeric 这个是比较强的,不仅能识别中文的数字,还能识别罗马数字
 
 
 
可迭代对象(列表、元组、、字典、字符串)
能进行for循环的就是可迭代对象
 
列表
切片
 
列表的清空
l1.clear()
推荐是用l1 = [] #这种直接给变量赋值一个空列表,效率高,只需要指针指向一下就ok
 
sorted(l) #python的内置函数,排序
l.sort(reverse=True) #从小到大排序
 
 
字典
python中唯一具有映射关系(一一对应,其实它可以一对多)的数据类型
字典的查询效率高于列表
列表是线性存储,字典存储空间比较大(因为它有一张映射表,以空间换时间)
字典的键唯一且是不可变的类型(整型,元组,字符串)
 
dict.get('name',None) #如果没取到name的值就返回一个None,并不会报错
 
 
None 并不是空,它的数据类型是NoneType
None的bool值是False
 
--------------------------------------------------------------------------------------------------------------------
for循环
for i in 序列(列表,元组,字符串,字典):
 
continue 结束本次循环继续下一循环
break 结束整个循环
 
 
range
2.7 xrange == 3.0 range
 
 
循环遍历字典其实遍历的是key值
d = {1:'test',2:'helloworld'}
for i in d:
print ("%s--->%s"%(i,d[i]))
 
l = [1,2,3,4,5,6]
for i,v in enumerate(l):
print (i,v)
 
enumerate(l,1) #1 表示从1开始
--------------------------------------------------------------------------------------------------------------------
while循环
while xxx:
print ("xxx")
 
 
 
 
 
 
 
 
 
 
 
字符编码:
 
 ##################################################################

基础回顾


#变量:

1 不能以数字特殊字符开头
2 不能以关键字

缩进:
if 2>1:
print("123")

print("123")

#运算符

算数运算符 + - * /
赋值运算符 = += —= *= /=
i=1
i+=1------->i=i+1
print(i)

比较运算符 == >= <= != > < (一定是布尔值)

逻辑运算符 and or not

关系运算符 is in not in

位运算符

长整型:

可变数据类型: 列表 字典
不可变数据类型 :整型 元组 字符串------>一旦创建,不能修改

 

浮点型:科学计数法 0.000123 1.23e-4
float double

布尔类型
True False

字符串(String):

s=""
s1=str()

重点的字符串方法:

strip()
" ".join(["I","am","world!"])
"hello world".split("l",1)
"hello world".index("q")
s.replace("world","Python")
print("hello %s,%s"%("sb","egon"))
print("hello {name}, his age is {age}".format(age=30,name="wusir"))
print("一".isdigit())

 

 

 

 

 

 

 


 


# 整型

 ################################################################

#


#对象.方法()

# a=1
# b=a
# a=2
#
# _a=2423
#
# print(a)
# print(b)
#
# print(False and False)
# print(False or False)
#
# print(0 and 2)
# print(1 and 2)
# print(1 and 0)
#
#
# print(2 in [1,2,3])
#
# #字符串
#
# #转义符号
# s='Let\'s go'
#
# print(r"\fsdghlfjdk.")

#查找:[:]

# s1="hello world"
#
# print(s1[1:4])
# print(s1[1:4:2])
# print(s1[-1])
# print(s1[:])
# print(s1[:8])
# print(s1[1:-1])
# print(s1[1:])
# print(s1[-3:-1])

#strip():把字符串开头和结尾的空格以及\n

#s=" hello\nworld".strip()
# s=" hello\nworld\n"
# s1=" hello\nworld\n".strip()
# s1="**hello\nworld\n***".strip("*")
# print(s)
# print(s1)

#拼接方法

# s="hello"+"world"+"I"+"am"+"python"
# print(s)
#
# print(" ".join(["I","am","world!"]))

#分割方法
# s="hello world".split("l",1) # ["he","lo world"]
# print(s)


#查找字符
# print("hello world".find("a",4))
# # print("hello world".rfind("l"))
#
# #
# print("hello world".index("q"))

#替换方法

# s="hello world"
# print(s.replace("world","Python"))
# print(s)


#居中显示
# print("hello world".center(50,"*"))
# print("hello world".ljust(50,"*"))


#字符串的格式化输出
#%s:字符串 %d:整型 %f:浮点型

# print("hello %s,%s"%("sb","egon"))
# print("hello %s, his age is %d"%("sb",35))
# print("hello %s, his age is %.4f"%("sb",35.53452345))


# print("hello {0}, his age is {1}".format("alex",34))
# print("hello {0}, his age is {1}".format(34,"alex"))
#
# print("hello {name}, his age is {age}".format(age=30,name="wusir"))
#
#
# print("hello {name}, his age is {age}".format_map({"name":"egon","age":1000}))

 

# print("一".isdecimal())
# print("一".isdigit())
# print("壹".isnumeric())

# print("hello world".capitalize())
# print("hello world".title())
#
# print("HELLO world".casefold())
# print("HELLO world".lower())

# print("HELLO\tworld")
# print("HELLO world".expandtabs())

# "HELLO world".rsplit()
# print("HELLO\n wor\nld\n".splitlines())
# print("HELLO\n wor\nld\n".split("\n"))

#print("HELLo world".zfill(10))

 


print(type(None))


# []
#
# ()
#
# {}
#
# 0

 

# print(bool(-1))
# print(bool([1,]))
# print(bool(None))
#
# if None:
# print("ok")

 #########################################################################

 

#创建形式 可迭代对象:能够进行for循环

l=[1,"hello",[4,5],{"name":"egon"}]
l2=list([1,23,3])
l3=[1,23,["hello",334],656,77]
# print(l2)
# print(type(l2))
#
# #查:切片[:]
# print(l3[-2:])

#增加

# l3.append("yuan")
# l3.append(7)
# print(l3)
# l3.insert(2,"jjj")
# print(l3)

#
# l3.extend([7,8])
# print(l3)

# ret=l3.pop(1)
# print(ret)
# print(l3)

# l3.remove(1)
# print(l3)

# del l3[2]
# print(l3)
# del l3
# print(l3)

#改 赋值操作

 

# print(id(l3))
#
# l3[2][0]="yuan"

# l4=[12,3]
#
# # l4.clear()
# # print(l4)
#
# l4=[] #推荐这种方式

# [1,222,33].count(33)

# len

# print(len(l3))
# #l5=[3,1,56,34]
# l5=["A","a","B"]
#
# l5.sort(reverse=True)

# print(l5)
# sorted(l5)
#
# [1,2,333,4].reverse()

# count=0
# for i in [11,22,33]:
# print("%s---%s"%(count,i))
#
# count+=1

# l=[1,2,333,4]
# for i in l:
# print(l.index(i),i)


# l=[1,2,333,4]
# for i ,v in enumerate(l,1):
# print(i,v)

 

 

# 0---11
# 1---22
# 2---33

 ###################################################


#python中唯一具有映射关系的数据类型: 字典的查询效率高于列表


#创建

#d={[1,2,3]:"yuan","name":"egon"}# 键唯一且为不可变数据类型
#d={1:"yuan","name":"egon"}# 键唯一且为不可变数据类型


#查
# print(d["name"])
#
# v=d.get("names",None) #推荐
# print(v)
#
# if not v:
# pass

#遍历

# for i in "hello":
# print(i)

#d={1:"yuan","name":"egon"}


# for i in d:
# #print(i,"----->",d[i])
# print("%s---->%s======"%(i,d[i]))

# print(list(d.keys()))
# print(d.values())
# print(d.items())


# 1---->"yuan"
# "name"---->"egon"


#增
d={1:"yuan","name":"egon"}

# d["age"]=123
# print(d)
#
#
# #修改
# d[1]=666
#
# print(d)

#删除

# ret=d.pop(1)
# print(ret)
# print(d)


# d2={"height":123,"sex":"male","name":"alex"}
#
# d.update(d2)
# print(d)

 

 ##############################################################

 

 

# for i in seq: # seq可以是字符串,列表,元组,字典
# pass
#
# print("ok")

 


# 两个问题:
# 1 循环次数有序列的一级元素的个数决定

#item是什么?

for item in ["hello",123,[2,3,4]]:
if item==123:
continue #结束的本次循环
#break # 结束的整个for循环
#print("ok")
print(item)

else:
print("ending for")

print("ending")

# print(range(10))
#
# for i in range(10):
# print("ok")

 

 


# while 条件表达式:
# 执行代码

#
# while 2>1:
# print("ok")


# 打印1-100

# i=1
# while i<101:
# print(i)
# break
# i+=1
#
# else:
# print("ok")

# for i in range(1,101):
# print(i)

 ####################################################################

 


#集合set 两个功能:1 去重 2关系测试

# s=set([1,3,"hello"])
# s2={1,2,3}
#
# print(s)
# print(type(s2))

#去重:
# l=[1,2,2,34,45]
# s="hello"
#
# print(set(l))
# print(set(s))

# print({{1,2}:"hello"})# set是可变数据类型
# print({[]:"hello"})

# s3={1,2,[1,2]} # set集合内元素一定是不可变数据类型
# print(s3)

#关系测试

s1={"hello",1,2,3}

s2={1,2,("a","b")}

# 求并集

print(s1.union(s2))
print(s1|s2)

# 求交集

print(s1.intersection(s2))
print(s1&s2)

# 求差集
print(s1.difference(s2))
print(s1-s2)

print(s2.difference(s1))
print(s2-s1)

#对称差集

print(s1.symmetric_difference(s2))
print(s2.symmetric_difference(s1))
print(s1^s2)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

 

posted @ 2017-07-27 22:44  wanchenxi  阅读(156)  评论(0编辑  收藏  举报