zoukankan      html  css  js  c++  java
  • Python基础

    2.1 编程语言介绍

    机器语言:

    特点:用计算机能看懂的0和1去写程序
    优点:程序运行速度快
    缺点:开发效率非常低

    汇编语言:

    特点:用一些英文标签代替一串二进制来写程序
    优点:比机器语言可阅读性强,操作系统大量使用汇编语言比如关于进程的调度(多道技术)代码就是汇编语言写的
    缺点:没有摆脱二进制编程的本质,开发效率低

    高级语言:

    特点:用人能读懂的(英文)字符去写程序
    优点:优点开发效率高
    缺点:必须经过翻译才能让计算机识别,导致运行速度慢

    总结:

    运行效率从高到底
    开发效率从低到高
    学习难度从难到易

    编译型:一次性翻译,拿编译后的结果直接给机器运行
    eg:c语言,需求编译器(如gcc,glibc)
    ??编译只需要点一次??

    解释型:一句一句解释成机器指令运行
    eg:python,需求解释器(如Cpython)

    2.2 执行python程序:

    eg: pythpn3 C: est.py 1. 启动python解释器(内存中) 2. 将C: est.py内容从硬盘读入内存(这一步与文本编辑器是一样的) 3. 执行读入内存的代码

    如果想要永久保存代码,就要用文件的方式
    如果想要调试代码,就要用交互式的方式

    2.3 变量

    一个是“变”:核心在变化
    一个是“量”:衡量,计量,表示一种状态

    变量的定义

    “变量名” + “赋值符号” + “变量的值”
    eg: name='egon'

    变量定义规则:

    1. 变量名只能是字母、数字或下划线的任意组合
    2. 变量的第一个字符不能是数字
    3. 一下关键字不能声明为变量名['and', 'as', 'assert', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'exec', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'not', 'or', 'pass', 'print', 'raise', 'return', 'try', 'while', 'with', 'yield']

    变量的修改

    定义一个变量,存储的数据是变量值
    变量名与变量值只是一种绑定关系,变量名本身没有存储值的功能
    python name='a' # 'a'这个值的引用计数+1 name='b' # 'b'这个值的引用计数+1,a这个值的引用计数-1 值的引用计数为0时,python解释器会定期回收这些值

    • 变量定义的三个重要组成部分:
      id(身份) 可用is/is not 判定
      type
      value(值) 可用'=='判定

    • 小数池:python特性,用来存放长度较短的数字

    常量:不变的量
    python中没有常量的专门定义方式
    通常用全部大写的变量名表示常量,仅仅只是一种提示效果

    赋值

    • 链式赋值
      a=b=c=d=e=f=10
    • 增量赋值
      +=,-=....
    • 交换赋值
      x,y = y,x
    • 值的解压
      ```python msg = 'hello'
      a,b,c,d,e = msg

    a,,,,e = msg
    a,*
    ,e = msg ```

    2.4 程序交互

    input

    input默认接受的内容为字符串

    python2中raw_input同python3的input,python2的input将输入的内容原封不动的传进来

    2.5 格式化输出

    %+字母

    python print('number:%d, string:%s' % (123,'str'))

    str.format()

    在使用%+字母的地方换成{}, ```python

    不加数字表示顺序输出

    print('number:{}, string:{}'.format(123,'st'))

    将()中视作列表,使用索引输出

    print('{2},{1},{0}'.format('a','b','c'))

    亦可索引嵌套索引

    print('{1[2]},{2},{0}'.format('a',('aa','bb','cc'),[1,2,3]))

    2.6 进制转换

    十进制

    0,1,2,3,4,5,6,7,8,9

    二进制

    0,1
    bin()

    八进制

    0,1,2,3,4,5,6,7
    oct()

    十六进制

    0,1,2,3,4,5,6,7,8,9,a,b,c,d,e
    hex()

    2.7 运算符

    常规运算符:

    +
    -
    *
    **
    /
    //
    %

    字符串、列表是有序的可用+、*运算符

    比较运算符:

    is >
    <
    >=
    <=
    ==
    !=

    赋值运算符:

    =
    +=
    -=
    *=
    /=
    \%=
    **=
    //=

    逻辑运算:

    and
    or
    in
    not

    2.8 流程控制

    if
    elif
    elif
    ...
    else
    ```python score = input('>>: ') score = int(score)

    if score >= 90: print('A') elif score >= 80: print('B') elif score >= 70: print('C') elif score >= 60: print('D') else: print('E') print('====>') ```

    2.9 循环控制

    1.while循环

    while 条件: 循环体的代码1 循环体的代码2 循环体的代码3 ```python

    2.while循环打印0-9

    count = 0 while count < 10: print(count) count += 1

    3.while死循环打印ok

    while True: #死循环 print('ok')

    4.while死循环打印ok2

    while 1: #死循环 print('ok')

    5.break语句打印0-4

    break:跳出本层循环 count = 0 while count < 10: if count == 5: break print(count) count += 1

    6.continue语句不打印4,5,6

    continue:跳出本次循环 0 1 2 3 7 8 9 count = 0 while count < 10: if count >=4 and count <=6: count += 1 continue print(count) count += 1

    7.猜年龄(死循环无限猜)

    OLDBOY_AGE = 56 while 1: age = input('猜一猜年龄>>: ') age = int(age)

    if age > OLDBOY_AGE:
        print('太大了')
    elif age < OLDBOY_AGE:
        print('太小了')
    else:
        print('猜对了')
        break
    

    8.猜年龄2(猜三次)(循环条件控制)

    OLDBOY_AGE = 56 count = 1 while count <= 3: age = input('猜一猜年龄>>: ') age = int(age)

    if age > OLDBOY_AGE:
        print('太大了')
        count += 1
    elif age < OLDBOY_AGE:
        print('太小了')
        count += 1
    else:
        print('猜对了')
        break
    

    9.猜年龄3(猜三次)(循环体if控制)

    OLDBOY_AGE = 56 count = 1 while True: if count > 3: print('您猜的次数超过限制') break age = input('猜一猜年龄>>: ') age = int(age)

    if age > OLDBOY_AGE:
        print('太大了')
    elif age < OLDBOY_AGE:
        print('太小了')
    else:
        print('猜对了')
        break
    count += 1
    

    10.分数变成绩

    while True: score = input('>>: ') score = int(score)

    if score >= 90:
        print('A')
    if score >= 80:
        print('B')
    if score >= 70:
        print('C')
    if score >= 60:
        print('D')
    if score < 60:
        print('E')
    

    11.猜年龄4(循环体if控制)(优化版本)

    OLDBOYAGE = 56 count = 0 while True: if count > 2: break age = input('猜一猜年龄>>: ') age = int(age) if age > OLDBOYAGE: print('太大了') if age < OLDBOYAGE: print('太小了') if age == OLDBOYAGE: print('猜对了') break count += 1 ```

    for循环

    不依赖索引
    for 单项 in 序列:
    循环体 python for item in dict: print(dicr[item]) for i in range(10,0,-2) print(i)

    2.10 基本数据类型

    数据是用来表示状态的,不同的状态就应该用不同的类型的数据去表示。
    编程就是为了模拟人的活动并替人工作,所以需要能够识别人类的信息,对应的就是不同数据结构表示不同的状态。

    数字

    整型int

    eg:年级,年纪,等级,身份证号,QQ号,手机号
    level=10

    浮点型float

    eg:身高,体重,价格,薪资,温度
    height=1.73
    salary=4.4

    字符串str

    包含在引号(单、双、三)里面,由一串字符组成
    eg:姓名,性别,地址,学历,密码
    name = 'chuck'

    基本使用:

    • 长度len
      name = 'chuck' print(len(name))
    • 索引
      print(name[2]) 注:只读,不可写
    • 切片
      print(name[2:])

    常用方法

    ```python

    !/usr/bin/python

    coding=utf-8

    import string

    strip

    name = 'chuck' print(name.strip('')) print(name.lstrip('')) print(name.rstrip(''))

    startwith, endwith判断开头结尾的字符是否符合

    name = 'handsome_chuck' print(name.endswith('ck')) print(name.startswith('hand'))

    replace替换字符

    name = "Egon say :i don't have one tesla, my name is egon" print(name.replace('egon', 'SB', 1))

    format格式化

    print('name:{}, age:{}, gender:{}'.format('chuck', 18, 'male')) print('{1}, {0}, {1}'.format('chuck', 18, 'male')) print('{name}, {age}, {gender}'.format(gender='male', name='chuck', age=18))

    find, rfind, index, rindex, count

    sentence = 'chuck say hello to everyone' print(sentence.find('o')) # 从左开始寻找符合的字符串 print(sentence.rfind('o')) # 从右开始寻找符合的字符串 print(sentence.index('o')) # 从左开始寻找符合的字符串,找不到报异常 print(sentence.rindex('o')) # 从右开始寻找符合的字符串,找不到报异常 print(sentence.count('o')) # 对符合条件的字符串计数

    split分割字符串为多串字符串

    name = 'root:x:0:0::/root:/bin/bash' print(name.split(':')) name = 'C:/a/b/c/d.txt' print(name.split('/', 1)) name = 'a|b|c' print(name.rsplit('|', 1))

    join将多串字符串链接为单个字符串

    tag = ' ' print(tag.join(['chuck', 'say', 'hello', 'to', 'world']))

    is数字系列

    num1 = b'4' num2 = u'4' num3 = '四' num4 = 'Ⅳ'

    isdigt:bytes,unicode

    print(num1.isdigit()) print(num2.isdigit()) print(num3.isdigit()) print(num4.isdigit())

    isdecimal:unicode

    print(num2.isdecimal()) print(num3.isdecimal()) print(num4.isdecimal())

    isnumberic:unicode,中文数字,罗马数字

    print(num2.isnumeric()) print(num3.isnumeric()) print(num4.isnumeric()

    上三者皆不可判断浮点数

    num5 = '4.5' print(num5.isdigit()) print(num5.isdecimal()) print(num5.isnumeric())

    总结:

    最常用的是isdigit,可以判断bytes和unicode类型,整型数字,这也是最常见的数字应用场景

    如果要判断中文数字或罗马数字,则需要用到isnumeric

    ```

    扩展方法

    ```python

    is其他

    print('=' * 20) name = 'SB1234' print(name.isalnum()) # 只能是字母数字 print(name.isalpha()) # 只能是字母 print(name.isidentifier()) # 是否包含关键字 print(name.islower()) # print(name.isupper()) print(name.isspace()) print(name.istitle())

    center, ljust, rjust, zfill

    name = 'the best chuck' print(name.center(30, '=')) # 将目标字符串在指定长度的字符串里居中 print(name.ljust(30, '')) # 将目标字符串在指定长度的字符串里靠左对齐 print(name.rjust(30, '')) # 将目标字符串在指定长度的字符串里靠右对齐 print(name.zfill(30))

    expandtabs 将制表符转换成空格

    name = 'chuck hello' print(name) print(name.expandtabs(1))

    lower, upper

    info = 'Chuck is belong to NASA.' print(info) print(info.lower()) # 将字符串全部小写 print(info.upper()) # 将字符串全部大写

    captalize, swapcasw, title

    print(info.capitalize()) # 仅第一个字符大写 print(info.swapcase()) # 字符串中大写变小写,小写变大写 print(info.title()) # 字符串每个单词首字母大写

    ```

    列表list

    以上都只是一个对象可处理,列表可以存多个对象,可以对多个对象进行处理(可变类型)
    eg:爱好,装备,购物车
    hobby = ['paly', 'eat', 'sleep']

    基本使用

    • 索引
      l = [1,2,3,4]
      print(l[2],l[3])
    • 切片

      ```python l = [1,2,3,4,5,6,7,8,9] print(l[1:4])
      print(l[1:5:2])

      '2'为指定步长

      print(l[-1]) print(l[]) ```

    • 包含
      l = [1,2,3,4,5] printf(2 in l)

    • list.index(x)
      返回列表中第一个值为 x 的元素的索引。如果没有匹配的元素就会返回一个错误。

      ```python

      print(l.index(2)) 1 ```

    常用方法

    • list.append(x)
      把一个元素添加到列表的结尾,相当于 a[len(a):] = [x]。 l.append(6)
    • list.extend(L)
      将一个给定列表中的所有元素都添加到另一个列表中,相当于 a[len(a):] = L。

    • list.insert(i, x)
      在指定位置插入一个元素。第一个参数是准备插入到其前面的那个元素的索引,例如 a.insert(0, x) 会插入到整个列表之前,而 a.insert(len(a), x) 相当于 a.append(x)。

    • list.remove(x)
      删除列表中值为 x 的第一个元素,返回None,如果没有这样的元素,就会返回一个错误。

    • list.pop([i])
      从列表的指定位置删除元素,并将其返回。如果没有指定索引,a.pop() 返回最后一个元素。元素随即从列表中被删除(方法中 i 两边的方括号表示这个参数是可选的,而不是要求你输入一对方括号,你会经常在Python 库参考手册中遇到这样的标记)。

    扩展方法

    • list.clear()
      从列表中删除所有元素。相当于 del a[:]。

    • list.count(x)
      返回 x 在列表中出现的次数。

    • list.sort(self,key,reverse)
      对列表中的元素就地进行排序。key为指定关键字排序,reverse指定正序或倒序

    • list.reverse()
      就地倒排列表中的元素。

    • list.copy()
      返回列表的一个浅拷贝。等同于 a[:]。

    模拟堆栈

    列表方法使得列表可以很方便的做为一个堆栈来使用,堆栈作为特定的数据结构,最先进入的元素最后一个被释放(后进先出)。用 append() 方法可以把一个元素添加到堆栈顶。用不指定索引的 pop() 方法可以把一个元素从堆栈顶释放出来。
    可用list.insert(i,x)&list.pop()
    list.append(x)&list.pop()
    两种方法模拟

    模拟队列

    你也可以把列表当做队列使用,队列作为特定的数据结构,最先进入的元素最先释放(先进先出)。不过,列表这样用效率不高。相对来说从列表末尾添加和弹出很快;在头部插入和弹出很慢(因为,为了一个元素,要移动整个列表中的所有元素)。

    要实现队列,使用 collections.deque,它为在首尾两端快速插入和删除而设计。 ```python

    from collections import deque queue = deque(["Eric", "John", "Michael"]) queue.append("Terry") # Terry arrives queue.append("Graham") # Graham arrives queue.popleft() # The first to arrive now leaves 'Eric' queue.popleft() # The second to arrive now leaves 'John' queue # Remaining queue in order of arrival deque(['Michael', 'Terry', 'Graham']) ```

    列表推导式

    列表推导式不局限于列表中使用

    ```python l1 = [x**2 for x in range(10)]

    l1、l2等价

    l2 = [] for x in range(10): x **= 2 l2.apeend(x)

    l3 = [x2 if x%2==0 else x3 for x in range(10)]

    l3、l4等价

    l4 = [] for x in range(10): if x % 2 == 0: x **= 2 else: x **= 3 l4.append(x) ```

    嵌套的列表推导式

    ```python

    matrix = [ [1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], ] [[row[i] for row in matrix] for i in range(4)]

    等价于:

    transposed = [] for i in range(4): transposed.append([row[i] for row in matrix])

    等价于:

    transposed = []

    for i in range(4): transposedrow = [] for row in matrix: transposedrow.append(row[i]) transposed.append(transposed_row)

    终极简版:

    list(zip(*matrix)) ```

    zip():需求多个等长序列,将每个序列的同等索引位的元素组合成元组,并返回元组组合的列表

    元组tuple

    元组就像字符串, 不可变的。通常包含不同种类的元素并通过分拆(参阅本节后面的内容) 或索引访问(如果是 namedtuples,甚至可以通过属性)。用来做查询功能,不具有其他功能,可以节省内存。
    - 元组可以作为字典的key

    ```python
    d = {(1,2,3): 'egon'}
    print(d, type(d), d[(1,2,3)])
    ```  
    
    • 元组不可变,但元组内部的元素可以是可变类型

      python t = (1,['a','b'],'sss',(1,2)) t[1][0] = 'A' print(t)

    字典dict

    字典以 关键字 为索引,关键字可以是任意不可变类型,通常用字符串或数值。

    如果元组中只包含字符串和数字,它可以做为关键字,如果它直接或间接的包含了可变对象,就不能当做关键字。不能用列表做关键字,因为列表可以用索引、切割或者 append() 和 extend() 等方法改变。

    {键key:键值value}
    key只能用不可变数据类型,键值value无限制

    可以看做无序的键: 值对 (key:value 对)集合
    取值:

    python print(dict[key]) print(dict.get('key', object))

    常用方法

    • 存/取

      • dict.get(self,k,default),返回k的value,失败返回设定的default,不报错
      • dict.pop(self,k,default),返回k的value,失败返回default
      • dict.popitem(self),返回key&value

      python info_dict = {'name':'chuck', 'age':18, 'sex':'male'} print(info_dict['name']) info_dict['level'] = 10 info_dict.get['ann',None] info_dict.pop['sex2', None] info_dict.popitem()

    • 删除

      python del info_dict['name']

    • dict.keys(self)
    • dict.items(self)
    • dict.values(self)
    • 循环取值

      ```python for k in infodict: print(k, infodict[k]) for k in info_dict.keys: print(k, infodict[k]) for val in infodict.values: print(val)

      for items in infodict.items: # items = (key, value) print(items) for k,v in infodict.items: # 将元组items的值解压出来给k,v
      print(k, v) ```

    • 长度用len()求取
    • 包含in
    • dict.update(kwargs) ()中接收一个字典,比对两个字典,相同的key取第二个字典的value,原字典没有的key&value补充进原字典
    • dict.setdefault(k, default)

      • key不存在则添加key,其值为default,若存在,不新建key,default不起任何作用

      python info_dict.setdefault('hobbyies',[]).append('study')

    • dict.copy(self)

      python d = info_dict.copy()

    • dict.clear() 清空字典
    • dict.fromkeys(seq, value)
      seq接收一个序列,将序列的每一个值作为key,对应相同的一个value,组合成一个字典。dict不对应任何一个具体的字典。
    • dict.get(k, default)
      取key为k的value,无则返回default

    循环使用

    • while()

      python while True: pass while 1: pass

    • for

    不依赖索引的取值

    ```python
    for item in dict:
        print(dicr[item])
    for i in range(10,0,-2)
        print(i)
    ```
    
    • items()

      • 循环字典时关键字和对应的值可以同时解读出来:

      python knights = {'gallahad': 'the pure', 'robin': 'the brave'} for k, v in knights.items(): print(k, v)

    • enumerate()

      • 在序列中循环时,索引位置和对应值可以同时得到:

      python for i, v in enumerate(['tic', 'tac', 'toe']): print(i, v)

    • 同时循环两个或更多的序列,可以使用 zip() 整体打包:

      python questions = ['name', 'quest', 'favorite color'] answers = ['lancelot', 'the holy grail', 'blue'] for q, a in zip(questions, answers): print('What is your {0}? It is {1}.'.format(q, a))

    • 逆向循环序列

      • 先正向定位序列,然后调用 reversed() 函数:

      python for i in reversed(range(1, 10, 2)):

    布尔bool

    True:1
    False:0

    集合set

    作用:去重,关系运算
    集合是一个无序不重复元素的集。基本功能包括关系测试和消除重复元素。集合对象还支持 union(联合),intersection(交),difference(差)和 sysmmetric difference(对称差集)等数学运算。
    大括号或 set() 函数可以用来创建集合。注意:想要创建空集合,你必须使用 set() 而不是 {}。
    集合元素的原则:
    1. 每个元素必须是不可变类型
    2. 没有重复的元素
    3. 无序

    关系运算

    • in &not in
    • 并集 |

      • set.union([set])

      python l1 = {1,2,3,4,5,7,8,90,0} l2 = {1,3,56,8,0,6,4,8,5} s = l1 | l2

    • 交集 &

      • set.intersection([set])

      python s2 = l1 & l2

    • 差集 -

      • set.difference([set])

      python s3 = l1 - l2 s4 = l2 - l1

    • 对称差集 ^

      • set.symmetric_difference([set])

      python s5 = l1 ^ l2

    • for

      python for item in l1: print l1

    • 解压

      python a, *_ = l1

    • ==

      python set1={1,2,3} set2={1,2,3} print(set1 == set2)

    • >,>= ,<,<= 父集,子集

      python set1={1,2,3,4,5} set2={1,2,3,4} print(set1 >= set2) print(set1.issuperset(set2)) print(set2 <= set1) print(set2.issubset(set1))

    主要方法

    • set.add(val)
      • set类型为可变类型,但是只能添加不可变类型
    • set.pop()
      • 随机删除某个元素并返回删除删除元素
    • set.remove(val)
      • 指定删除某个元素,若无该元素则报错
    • set.discard(val)
      • 指定删除某个元素,元素不存在不会报错

    扩展

    • set.update([set])
    • set.cpoy()
    • set.clear()
    • set.difference_update([set2])
      • set 与set2的差集替换set,但不改变set的id

    可变数据类型与不可变数据类型

    • 可变数据类型:不可哈希类型,列表,字典,deque,

      • id不变的时候,数据类型内部元素的value可变
      • 这些元素可以存多个对象,并且修改这些对象
    • 不可变数据类型:可哈希类型,数值,字符串,bool,元组

      • value改变,id也跟着改变

      ```python

      num = 10 id(num) 1793701216 type(num) <class 'int'> num 10 num='abc' id(num) 37460331576 type(num) <class 'str'> num 'abc' x=1.3 id(x) 37457305864 type(x) <class 'float'> x=2.3 id(x) 37457305888 type(x) <class 'float'> x = 'hello' id(x) 37464353344 type(x) <class 'str'> x[0] 'h' ```

    字符编码

    前言

    1. 文本编辑器存取文件的原理(nodepad++,pycharm,word)
      打开编辑器就打开了启动了一个进程,是在内存中的,所以在编辑器编写的内容也都是存放与内存中的,断电后数据丢失。
      因而需要保存到硬盘上,点击保存按钮,就从内存中把数据刷到了硬盘上。
      在这一点上,我们编写一个py文件(没有执行),跟编写其他文件没有任何区别,都只是在编写一堆字符而已。
    2. python解释器执行py文件的原理 ,例如python test.py
      • 第一阶段:python解释器启动,此时就相当于启动了一个文本编辑器
      • 第二阶段:python解释器相当于文本编辑器,去打开test.py文件,从硬盘上将test.py的文件内容读入到内存中
      • 第三阶段:python解释器解释执行刚刚加载到内存中test.py的代码
    3. 总结:
      python解释器是解释执行文件内容的,因而python解释器具备读py文件的功能,这一点与文本编辑器一样。
      与文本编辑器不一样的地方在于,python解释器不仅可以读文件内容,还可以执行文件内容。

    什么是字符编码

    计算机要想工作必须通电,也就是说‘电’驱使计算机干活,而‘电’的特性,就是高低电平(高低平即二进制数1,低电平即二进制数0),也就是说计算机只认识数字,编程的目的是让计算机干活,而编程的结果说白了只是一堆字符,也就是说我们编程最终要实现的是:一堆字符驱动计算机干活
    所以必须经过一个过程:
    字符--------(翻译过程)------->数字
    这个过程实际就是一个字符如何对应一个特定数字的标准,这个标准称之为字符编码
    以下两个场景下涉及到字符编码的问题:
    1. 一个python文件中的内容是由一堆字符组成的
    2. python中的数据类型字符串是由一串字符串组成的

    字符编码的发展史

    ASCII

    • 计算机起源阶段,仅有将英文进行编码
      ASCII:一个Bytes代表一个字符(英文字符/键盘上的所有其他字符),1Bytes=8bit,8bit可以表示0-(2^8-1)种变化,即可以表示256个字符
      ASCII最初只用了后七位,127个数字,已经完全能够代表键盘上所有的字符了(英文字符/键盘的所有其他字符)
      后来为了将拉丁文也编码进了ASCII表,将最高位也占用了

    GBK和其他编码

    • 使用其他语言的国家,自行定制编码 GBK:2Bytes代表一个字符
      为了满足其他国家,各个国家纷纷定制了自己的编码
      日本把日文编到Shift_JIS里,韩国把韩文编到Euc-kr里

    unicode&UTF-8

    • 各国有各国的标准,就会不可避免地出现冲突,结果就是,在多语言混合的文本中,显示出来会有乱码。
      unicode, 统一用2Bytes代表一个字符, 2**16-1=65535,可代表6万多个字符,因而兼容万国语言。
      但对于通篇都是英文的文本来说,这种编码方式无疑是多了一倍的存储空间(二进制最终都是以电或者磁的方式存储到存储介质中的)。
      于是产生了UTF-8,对英文字符只用1Bytes表示,对中文字符用3Bytes。
    • unicode VS UTF-8
      • unicode:简单粗暴,所有字符都是2Bytes,
        • 优点是字符->数字的转换速度快,
        • 缺点是占用空间大
      • utf-8:精准,对不同的字符用不同的长度表示,
        • 优点是节省空间,
        • 缺点是:字符->数字的转换速度慢,因为每次都需要计算出字符需要多长的Bytes才能够准确表示
      • 内存中使用的编码是unicode,用空间换时间(程序都需要加载到内存才能运行,因而内存应该是尽可能的保证快)
      • 硬盘中或者网络传输用utf-8,网络I/O延迟或磁盘I/O延迟要远大与utf-8的转换延迟,而且I/O应该是尽可能地节省带宽,保证数据传输的稳定性。

    所有程序,最终都要加载到内存,程序保存到硬盘不同的国家用不同的编码格式,但是到内存中我们为了兼容万国(计算机可以运行任何国家的程序原因在于此),统一且固定使用unicode,这就是为何内存固定用unicode的原因,你可能会说兼容万国我可以用utf-8啊,可以,完全可以正常工作,之所以不用肯定是unicode比utf-8更高效啊(uicode固定用2个字节编码,utf-8则需要计算),但是unicode更浪费空间,没错,这就是用空间换时间的一种做法,而存放到硬盘,或者网络传输,都需要把unicode转成utf-8,因为数据的传输,追求的是稳定,高效,数据量越小数据传输就越靠谱,于是都转成utf-8格式的,而不是unicode。

    字符编码分类--字符编码的使用

    - 文件执行的过程:
    某个能打开文件的程序启动--->将需要打开的文件从硬盘加载进内存--->程序按照自己的规则操作文件

    • 字符编码会在两个阶段使用:
      1. 文件从硬盘加载进内存 & 文件从内存存入硬盘
      2. 程序按照自己的规则操作文件
    • 内存默认编码格式为Unicode
    • 硬盘通常使用UTF-8格式

    结论: 1. 文件以什么编码encode的,就以什么编码decode 2. python3默认的解码格式是UTF-8,可以在文件头更改 3. python2默认解码格式是ASCII,可以在文件头更改 4. python2默认字符串格式为默认文件解码格式encode之后的bytes,可以手动加上u改为Unicode 5. python3默认字符串格式为Unicode,可以使用encode方法改成其他编码格式的bytes

    文件从硬盘加载进内存 & 文件从内存存入硬盘

    notepad++

    分析过程?什么是乱码

    文件从内存刷到硬盘的操作简称存文件

    文件从硬盘读到内存的操作简称读文件

    • 乱码一:存文件时就已经乱码

    存文件时,由于文件内有各个国家的文字,我们单以shiftjis去存,

    本质上其他国家的文字由于在shiftjis中没有找到对应关系而导致存储失败,用open函数的write可以测试,f=open('a.txt','w',encodig='shift_jis')

    f.write('你瞅啥 何を見て ') #'你瞅啥'因为在shiftjis中没有找到对应关系而无法保存成功,只存'何を見て '可以成功

    但当我们用文件编辑器去存的时候,编辑器会帮我们做转换,保证中文也能用shiftjis存储(硬存,必然乱码),这就导致了,存文件阶段就已经发生乱码

    此时当我们用shiftjis打开文件时,日文可以正常显示,而中文则乱码了

    • 乱码二:存文件时不乱码而读文件时乱码

    存文件时用utf-8编码,保证兼容万国,不会乱码,而读文件时选择了错误的解码方式,比如gbk,则在读阶段发生乱码,读阶段发生乱码是可以解决的,选对正确的解码方式就ok了,而存文件时乱码,则是一种数据的损坏。

    pycharm

    reload与convert的区别:

    pycharm非常强大,提供了自动帮我们convert转换的功能,即将字符按照正确的格式转换

    要自己探究字符编码的本质,还是不要用这个

    我们选择reload,即按照某种编码重新加载文件
    无论是何种编辑器,要防止文件出现乱码(请一定注意,存放一段代码的文件也仅仅只是一个普通文件而已,此处指的是文件没有执行前,我们打开文件时出现的乱码)

    核心法则就是,文件以什么编码保存的,就以什么编码方式打开
    - 以GBK编码写入一段汉字保存,以UTF-8打开,显示乱码 - 以utf编码写入一段汉字保存,以GBK打开正常显示 - 以GBK编码写入一段汉字保存,在文件开头指定解码格式(coding:utf-8),正常显示

    程序按照自己的规则操作文件-----探究python3和python2的字符串的编码

    python3:
    name = "林" # 整行字符都是以Unicode格式的二进制存在内存中,python解释器解释到赋值符"="时,新开辟一个内存空间的时候,以Unicode格式的二进制将”林“存进这个新开辟的内存空间
    python2: name = "林" # 整行字符都是以Unicode格式的二进制存在内存中,python解释器解释到赋值符"="时,新开辟一个内存空间的时候,都是已经encode后的格式存进去,即bytes,bytes是unicode格式encode之后的结果,encode的编码格式取决于文件开头指定的编码格式,若没有指定则为ANSCII编码

    python2中字符串有两种形式: 1. str=bytes 2. u""
    python3中字符串也有两种形式: 1. u"" 2. bytes

    数据传输必须用bytes
    bytes来自于Unicode格式的二进制按照默认的编码格式encode之后的结果,默认的编码格式来自于文件开头指定的编码格式

  • 相关阅读:
    一文解读AI芯片之间的战争 (转)
    一文解读ARM架构 (转)
    一文解读云计算 (转)
    一文解读裸金属云 (转)
    一文解读发布策略 (转)
    C#使用OracleDataReader返回DataTable
    centos8平台上php7.4的生产环境配置
    centos8安装php7.4
    centos8安装java jdk 13
    docker的常用操作之二:docker内无法解析dns之firewalld设置等
  • 原文地址:https://www.cnblogs.com/richiewlq/p/8455798.html
Copyright © 2011-2022 走看看