前言
为什么很多编程里都有指针这个东西,python好像没有吧…
是…真的没有指针
这个东西吗?
不!但…不完全是…
指针?内存!
在很多语言中指针是指一个变量它指向着另一个变量的地址
简单来说就是有一个变量a,另一个变量b是a的指针,那么b变量的值就是a的内存地址
可是!
在Python里这不是指针,是内存访问!
bytes与bytearray
在说bytearray
前我们先说bytes
bytes
它的构造是这样子的
bytes([source[, encoding[, errors]]])
- sourc(以下摘自Python的文档)
- 如果是一个 string,您必须提供 encoding 参数(errors 参数仍是可选的);bytes() 会使用
str.encode()
方法来将 string 转变成 bytes。 - 如果是一个
integer
,会初始化大小为该数字的数组,并使用 null 字节填充。 - 如果是一个遵循缓冲区接口的对象,该对象的只读缓冲区将被用来初始化字节数组。
- 如果是一个
iterable
可迭代对象,它的元素的范围必须是0 <= x < 256
的整数,它会被用作数组的初始内容。
- 如果是一个 string,您必须提供 encoding 参数(errors 参数仍是可选的);bytes() 会使用
- encoding
- 如果懒得用
str.encode()
的话,可以直接在这个参数里面写
- 如果懒得用
- error(不常用)
- errors(与source和encoding参数一起使用时可能需要):此参数指定了在编码过程中遇到无法编码的字符时的错误处理方式。常见的处理方式包括’strict’(默认值,遇到错误时抛出异常)、‘ignore’(忽略无法编码的字符)、‘replace’(用特定字符替换无法编码的字符)等。如果source不是字符串,或者没有指定encoding参数,则不需要此参数。可以看Python官方文档
bytearray
bytearray([source[, encoding[, errors]]])
和bytes
的构造是一样的
但bytes
是只读的
而bytearray
是可改的
我们后面在来聊这个东西
memoryview
python里面有一个对象:
memoryview()
这个玩意是可以访问到内存的,和id
函数一样
但是他们取得值是一样的
我们可以可以运行一下代码:
a = "hallo world".encode("utf-8")
p = bytearray(a)
'''
上面这两行代码也可以写成这样:
a = "hallo world"
p = bytearray(a,"utf-8")
'''
point = memoryview(p)
print(point) # <memory at 0x...> 其中0x...是一个十六进制数
print(id(point)) # 一个整数
print(eval(str(point.__repr__()).split("at ")[-1][:-1])) # 解析"<memory at "后的十六进制数
我们可以看到这两个数是一样的
什么?你眼力不行?可以用这个代码:print(id(point)==eval(str(point.__repr__()).split("at ")[-1][:-1]))
,结果是True!(别跟我说True是什么意思
它还支持切片
a = "hallo world"
a = bytearray(a,"utf-8")
point = memoryview(a)
print(point[0]) # 104
print(chr(point[0])) # h
我们也可以修改切片的值
假如修改memoryveiw的值会发现像指针一样把原来的东西修改
a = "hallo world"
a = bytearray(a,"utf-8")
print(a) # bytearray(b'hallo world')
point = memoryview(a)
point[0] = ord("b")
print(a) # bytearray(b'ballo world')
在这里插句嘴:
chr
是把一个ASCII码转成一个字符串
ord
是把一个字符串转成ASCII码
你说你想知道这个东西原来是什么样子的?前面的bytearray什么什么的不要?可以用decode
函数:
bytes.decode(encoding='utf-8', errors='strict')
bytearray.decode(encoding='utf-8', errors='strict')
- encoding
- 指编码格式一般用utf-8
- errors(不常用)
- 看上面介绍bytes的那一条或者是Python官方文档
- 返回值
- 一个str对象
我们可以把上面的代码改一改:
a = "hallo world"
a = bytearray(a,"utf-8")
print(a) # bytearray(b'hallo world')
print(a.decode("utf-8")) # hallo world
point = memoryview(a)
point[0] = ord("b")
print(a) # bytearray(b'ballo world')
print(a.decode("utf-8")) # ballo world
再谈bytes和bytearray
我们经常写的b"hallo"
前面的b
是只读的
你还不信?!看下面的代码就行了
注意
bytes
和bytearray
对象的方法不接受字符串作为其参数,就像字符串的方法不接受bytes
对象作为其参数一样。 例如,你必须使用以下写法:
a = "abc"
b = a.replace("a", "f")
和:
a = b"abc"
b = a.replace(b"a", b"f")
可读与只读
我们把上面的代码复制一下
读取
这个是读取的代码
a = "hallo world"
a = bytes(a,"utf-8")
point = memoryview(a)
print(point[0]) # 104
print(chr(point[0])) # h
# -----
a = "hallo world"
a = bytearray(a,"utf-8")
point = memoryview(a)
print(point[0]) # 104
print(chr(point[0])) # h
很显然,两个都不会报错
写入
这个是写入的代码
a = "hallo world"
a = bytearray(a,"utf-8")
point = memoryview(a)
point[0] = ord("b")
print(a) # bytearray(b'ballo world')
print(a.decode("utf-8")) # ballo world
# -----
a = "hallo world"
a = bytes(a,"utf-8")
point = memoryview(a)
point[0] = ord("b") # 报错:TypeError: cannot modify read-only memory
print(a)
print(a.decode("utf-8"))
bytearray是正常的
而bytes报错了,因为它是只读的
这个报错cannot modify read-only memory
翻译是无法修改只读存储器
你不是不信我说我写的b"hallo"的b是只读的吗?上代码!
a = b"hallo world"
point = memoryview(a)
point[0]=ord("b") # 报错:TypeError: cannot modify read-only memory
print(a)
现在信我了吧!
关于中文
我们一般用的编码是utf-8
,一个中文是由3个字节存储的(就是3个char)
还有以下有一些易错点:
print(b"你") # SyntaxError: bytes can only contain ASCII literal characters.
print(bytes("你")) # TypeError: string argument without an encoding
print(bytes("你","utf-8"))
前两行是因为只可以在ASCII里面的字符,要utf-8
解码
我们可以看到最后一行输出的是b'\xe4\xbd\xa0'
所以我们不能直接像前面改字母一样使用point[0] = ord("b")
来修改,不然就会解不了码:UnicodeDecodeError: 'utf-8' codec can't decode byte 0x... in position ...: invalid start byte
修改的话可以这样:
point[start:end] = bytes("字","utf-8")
start和end
:文字的搜引,记住一个文字算3,一个字母算1,比如"a你好"=>“你"是”[1:4]“,“好"是”[4:]”
后文
啊!..终于写完了!!!
啊?!!晚上了?!