Python 3.x Python3:以字节表示的x作为单词

Python 3.x Python3:以字节表示的x作为单词,python-3.x,binary-data,Python 3.x,Binary Data,我有一个python3脚本,它使用 fp = open("filename", 'rb') data = fp.read(count) 我不完全理解(即使在阅读了文档之后)read()返回的内容。它似乎是某种二进制数据,是可编辑的。但这不是一份清单 令人困惑的是,在脚本的其他地方,列表用于二进制数据 frames = [] # then later... inside a loop for ... data = b''.join(frames) 不管怎样。。。我想

我有一个python3脚本,它使用

fp = open("filename", 'rb')
data = fp.read(count)
我不完全理解(即使在阅读了文档之后)
read()
返回的内容。它似乎是某种二进制数据,是可编辑的。但这不是一份清单


令人困惑的是,在脚本的其他地方,列表用于二进制数据

frames = []
# then later... inside a loop
for ...
    data = b''.join(frames)
不管怎样。。。我想以单词为单位(也称为2字节块)迭代
read()
返回的对象

目前,脚本包含这个for循环

for c in data:
    # do something
是否可以更改
c
,使此循环在字(2字节块)而不是单个字节上迭代

编辑: 我不能在循环中使用
read()
一次读取2个字节。

我们可以使用
.read(n)
(就像它从以文本模式打开的文件中读取
n
Unicode代码点一样)以二进制模式显式读取(最多)
n
字节。这是一个阻塞调用,只会在文件末尾读取较少的字节

我们可以使用
iter
的双参数形式构建一个迭代器,该迭代器重复调用一个可调用的:

>>> help(iter)
Help on built-in function iter in module builtins:

iter(...)
    iter(iterable) -> iterator
    iter(callable, sentinel) -> iterator

    Get an iterator from an object.  In the first form, the argument must
    supply its own iterator, or be a sequence.
    In the second form, the callable is called until it returns the sentinel.
文件末尾的
read
将开始返回空结果,并且不会引发异常,因此我们可以将其用于sentinel

综合起来,我们得到:

for pair in iter(lambda: fp.read(2), b''):

在循环中,我们将获得表示两个字节数据的
字节
对象。您应该查看文档以了解如何使用这些工具。

从最简单的字面意义上讲,类似这样的东西可以让您每次循环两个字节

with open("/etc/passwd", "rb") as f:
    w = f.read(2)
    while len(w) > 0:
        print( w  )
        w = f.read(2)
至于您从
读取
中获得的内容,它是一个
字节
对象,因为您已将“b”指定为“打开”选项


我认为一种更为python的表达方式是通过迭代器或生成器。

以二进制模式读取文件时,将返回一个
字节
对象,这是标准python内置项之一。通常,其在代码中的表示形式类似于字符串,只是前缀为
b”“
——当您尝试打印它时,每个字节可能会显示一个转义符,如
\x**
,其中
**
是与字节值0到255对应的两个十六进制数字,或直接作为单个可打印ascii字符,使用与数字相同的ascii码点。您可以阅读更多关于这个和方法等字节(也类似于字符串)

似乎已经有了。给出了在
字节
对象中创建单个字节的
列表
的示例:

L=[bytes_obj[i:i+1]表示范围内的i(len(bytes_obj))]
我想这样修改它会对您有用:

L=[bytes_obj[i:i+2]表示范围内的i(0,len(bytes_obj),2)]
例如:

by=b“\x00\x01\x02\x03\x04\x05\x06”
#file.read()返回的对象也是字节,与上面的一样
words=[by[i:i+2]表示范围(0,len(by),2)内的i]
印刷品(字)
#输出-->[b'\x00\x01',b'\x02\x03',b'\x04\x05',b'\x06']
或者,如果您的列表可能太大,无法立即有效存储,请创建一个生成器,以相同的方式生成单词:

def get_单词(bytesobject):
对于范围内的i(0,len(bytesobject),2):
产生字节对象[i:i+2]

“我不完全理解(即使在阅读文档之后)read()返回的内容。它似乎是某种二进制数据,是可编辑的。但它不是列表。”您找到文档了吗?它就在那里说,
以二进制模式打开的文件(包括mode参数中的'b')以字节对象的形式返回内容,而不进行任何解码
,并且单词
字节
链接到该类型的文档。“令人困惑的是,在脚本的其他地方,列表用于二进制数据。”,它大概包含使用
b'
join
方法连接的
bytes
对象(另一个
bytes
对象)。您希望
c
是什么类型的对象?在其当前形式中,
c
将是一个
int
。但是,在“2字节块”中,它将是一个
bytes
对象。@KarlKnechtel似乎是
open()
的文档?不是
read()
。是的,这是
open()
的文档
open()
是如何创建文件对象的,其中的文档说明了如何使用这些对象
.read()
是文件对象的一种方法,因此您可以从中获得相应的文档。好的,谢谢,这非常有用。看来我问错问题了。也许我应该问,“为什么迭代字节对象返回
int
s”也许我应该问,“为什么迭代字节对象返回int?”“因为
bytes
对象表示内存字节序列,而解释8位值的最简单方法是将其解释为8位无符号整数?”?对我来说似乎是对的。当然,我发现它在过去很有用。我不知道你还期望什么;它不是字符串类型(在3.x中;坦率地说,2.x设计有很多缺陷)。