再谈⼩数据池,is和==的区别,,编码的问题 魔术手Jack

本节主要内容:

  1. ⼩数据池
  2. is和==的区别
  3. 编码的问题
    ⼀. ⼩数据池
    在说⼩数据池之前. 我们先看⼀个概念. 什么是代码块:
    根据提示我们从官⽅⽂档找到了这样的说法:
    A Python program is constructed from code blocks. A block is a piece of
    Python program text that is executed as a unit. The following are blocks: a
    module, a function body, and a class definition. Each command typed
    interactively is a block. A script file (a file given as standard input to
    the interpreter or specified as a command line argument to the interpreter)
    is a code block. A script command (a command specified on the interpreter
    command line with the ‘-c‘ option) is a code block. The string argument
    passed to the built-in functions eval() and exec() is a code block.
    A code block is executed in an execution frame. A frame contains some
    administrative information (used for debugging) and determines where and
    how execution continues after the code block’s execution has completed.
    粗略的翻译:
    python程序是由代码块构成的. ⼀个代码块的⽂本作为python程序执⾏的单元.
    代码块: ⼀个模块, ⼀个函数, ⼀个类, 甚⾄每⼀个command命令都是⼀个代码块. ⼀个⽂件也是⼀
    个代码块, eval()和exec()执⾏的时候也是⼀个代码块
    什么是命令⾏?
    我们在控制台CMD中输入python进入的就是python的command模式. 在这⾥也可以写
    python的程序.
    ⽽根据上⾯的官⽅的解释来看. ⼀个command命令就是⼀个python代码块
    在这里插入图片描述
    ⼆. 接下来我们来看⼀下⼩数据池 is和==的区别
  4. id()
    通过id()我们可以查看到⼀个变量表⽰的值在内存中的地址.
    s = ‘alex’
    print(id(s)) # 4326667072
  5. is和==
    == 判断左右两端的值是否相等. 是不是⼀致.
    is 判断左右两端内容的内存地址是否⼀致. 如果返回True, 那可以确定这两个变量使
    ⽤的是同⼀个对象
    在这里插入图片描述我们可以这样认为. 如果内存地址相同. 那么值⼀定是相等的. 如果值相等. 则不⼀定是同⼀
    个对象
    ⼩数据池. ⼀种数据缓存机制. 也被称为驻留机制. 各⼤编程语⾔中都有类似的东⻄. 在⽹上
    搜索常量池,⼩数据池指的都是同⼀个内容.
    ⼩数据池只针对: 整数, 字符串, 布尔值. 其他的数据类型不存在驻留机制

对于整数,Python官⽅⽂档中这么说:
The current implementation keeps an array of integer objects for all
integers between -5 and 256, when you create an int in that range you
actually just get back a reference to the existing object. So it should be
possible to change the value of 1. I suspect the behaviour of Python in
this case is undefine

对于字符串:
Incomputer science, string interning is a method of storing only onecopy of
each distinct string value, which must be immutable. Interning string
makes some stringprocessing tasks more time- or space-efficient at the cost
of requiring moretime when the string is created or interned. The distinct
values are stored ina string intern pool. –引⾃维基百科

在python中对-5到256之间的整数会被驻留在内存中. 将⼀定规则的字符串缓存. 在使⽤
的时候, 内存中只会创建⼀个该数据的对象. 保存在⼩数据池中. 当使⽤的时候直接从⼩数据
池中获取对象的内存引⽤. ⽽不需要创建⼀个新的数据. 这样会节省更多的内存区域.

优点: 能够提⾼⼀些字符串, 整数的处理速度. 省略的创建对象的过程.
缺点: 在’池’中创建或者插入新的内容会花费更多的时间.

对于数字: -5~256是会被加到⼩数据池中的. 每次使⽤都是同⼀个对象.
对于字符串:

  1. 如果字符串的⻓度是0或者1, 都会默认进⾏缓存
  2. 字符串⻓度⼤于1, 但是字符串中只包含字⺟, 数字, 下划线时才会缓存
  3. ⽤乘法的到的字符串. ①. 乘数为1, 仅包含数字, 字⺟, 下划线时会被缓存. 如果
    包含其他字符, ⽽⻓度<=1 也会被驻存, ②. 乘数⼤于1 . 仅包含数字, 字⺟, 下划
    线这个时候会被缓存. 但字符串⻓度不能⼤于20
  4. 指定驻留. 我们可以通过sys模块中的intern()函数来指定要驻留的内容.
    OK. 到⽬前为⽌. 我们已经了解了python的⼩数据池的⼀些基本情况了. 但是!!! 还有最后⼀
    个问题. ⼩数据池和最开始的代码块有什么关系呢?
    同样的⼀段代码在命令⾏窗⼝和在py⽂件中. 出现的效果是完全不⼀样的.
    a = 1000
    b = 1000
    print(a is b)
    注意. 在py⽂件中.得到的结果是True, 但是在command中就不是了.
    在代码块内的缓存机制是不⼀样的. 在执⾏同⼀个代码块的初始化对象的命令时, 会检
    查是否其值是否已经存在, 如果存在, 会将其重⽤. 换句话说: 执⾏同⼀个代码块时, 遇到初始
    化对象的命令时,他会将初始化的这个变量与值存储在⼀个字典中, 在遇到新的变量时, 会先
    在字典中查询记录, 如果有同样的记录那么它会重复使⽤这个字典中的之前的这个值. 所以在
    你给出的例⼦中, ⽂件执⾏时(同⼀个代码块) 会把a, b两个变量指向同⼀个对象.
    如果是不同的代码块, 他就会看这个两个变量是否是满⾜⼩数据池的数据, 如果是满⾜
    ⼩数据池的数据则会指向同⼀个地址. 所以: a, b的赋值语句分别被当作两个代码块执⾏, 但
    是他们不满⾜⼩数据池的数据所以会得到两个不同的对象, 因⽽is判断返回False.

三. 编码的补充

  1. python2中默认使⽤的是ASCII码. 所以不⽀持中⽂. 如果需要在Python2中更改编码.
    需要在⽂件的开始编写:

-- encoding:utf-8 --

  1. python3中: 内存中使⽤的是unicode码.
    编码回顾:
  2. ASCII : 最早的编码. ⾥⾯有英⽂⼤写字⺟, ⼩写字⺟, 数字, ⼀些特殊字符. 没有中⽂,
    8个01代码, 8个bit, 1个byte
  3. GBK: 中⽂国标码, ⾥⾯包含了ASCII编码和中⽂常⽤编码. 16个bit, 2个byte
  4. UNICODE: 万国码, ⾥⾯包含了全世界所有国家⽂字的编码. 32个bit, 4个byte, 包含了
    ASCII
  5. UTF-8: 可变⻓度的万国码. 是unicode的⼀种实现. 最⼩字符占8位
    1.英⽂: 8bit 1byte
    2.欧洲⽂字:16bit 2byte
    3.中⽂:24bit 3byte

综上, 除了ASCII码以外, 其他信息不能直接转换.
在python3的内存中. 在程序运⾏阶段. 使⽤的是unicode编码. 因为unicode是万国码. 什么内
容都可以进⾏显⽰. 那么在数据传输和存储的时候由于unicode比较浪费空间和资源. 需要把
unicode转存成UTF-8或者GBK进⾏存储. 怎么转换呢. 在python中可以把⽂字信息进⾏编码编码之后的内容就可以进⾏传输了. 编码之后的数据是bytes类型的数据.其实啊. 还是原来的
数据只是经过编码之后表现形式发⽣了改变⽽已.
bytes的表现形式:

  1. 英⽂ b’alex’ 英⽂的表现形式和字符串没什么两样
  2. 中⽂ b’\xe4\xb8\xad’ 这是⼀个汉字的UTF-8的bytes表现形式
    字符串在传输时转化成bytes=> encode(字符集)来完成
    s = “alex”
    print(s.encode(“utf-8”)) # 将字符串编码成UTF-8
    print(s.encode(“GBK”)) # 将字符串编码成GBK
    结果:
    b’alex’b’alex’
    s = “中”
    print(s.encode(“UTF-8”)) # 中⽂编码成UTF-8
    print(s.encode(“GBK”)) # 中⽂编码成GBK
    结果:
    b’\xe4\xb8\xad’
    b’\xd6\xd0’
    记住: 英⽂编码之后的结果和源字符串⼀致. 中⽂编码之后的结果根据编码的不同. 编码结果
    也不同. 我们能看到. ⼀个中⽂的UTF-8编码是3个字节. ⼀个GBK的中⽂编码是2个字节
    编码之后的类型就是bytes类型. 在⽹络传输和存储的时候我们python是保存和存储的bytes
    类型. 那么在对⽅接收的时候. 也是接收的bytes类型的数据. 我们可以使⽤decode()来进⾏解
    码操作. 把bytes类型的数据还原回我们熟悉的字符串:
    s = “我叫李嘉诚”
    print(s.encode(“utf-8”)) #
    b’\xe6\x88\x91\xe5\x8f\xab\xe6\x9d\x8e\xe5\x98\x89\xe8\xaf\x9a’
    print(b’\xe6\x88\x91\xe5\x8f\xab\xe6\x9d\x8e\xe5\x98\x89\xe8\xaf\x9a’.deco
    e(“utf-8”)) # 解码
    编码和解码的时候都需要制定编码格式.
    s = “我是⽂字”
    bs = s.encode(“GBK”) # 我们这样可以获取到GBK的⽂字

把GBK转换成UTF-8

⾸先要把GBK转换成unicode. 也就是需要解码

s = bs.decode(“GBK”) # 解码

然后需要进⾏重新编码成UTF-8

bss = s.encode(“UTF-8”) # 重新编码
print(bs

猜你喜欢

转载自blog.csdn.net/HZY199321/article/details/86478980
今日推荐