Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/296.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Python中,确定对象是否是类似字节的对象的正确方法是什么?_Python_Python 3.x - Fatal编程技术网

在Python中,确定对象是否是类似字节的对象的正确方法是什么?

在Python中,确定对象是否是类似字节的对象的正确方法是什么?,python,python-3.x,Python,Python 3.x,我的代码需要str,但会以以下方式处理传递字节的情况: if isinstance(data, bytes): data = data.decode() 不幸的是,这在bytearray的情况下不起作用。是否有一种更通用的方法来测试对象是字节还是字节,还是我应该检查两者?hasattr('decode')是否像我感觉的那样糟糕?您可以使用: isinstance(data, (bytes, bytearray)) 由于这里使用的基类不同 >>> bytes.__ba

我的代码需要
str
,但会以以下方式处理传递
字节的情况:

if isinstance(data, bytes):
    data = data.decode()
不幸的是,这在
bytearray
的情况下不起作用。是否有一种更通用的方法来测试对象是
字节
还是
字节
,还是我应该检查两者?
hasattr('decode')
是否像我感觉的那样糟糕?

您可以使用:

isinstance(data, (bytes, bytearray))
由于这里使用的基类不同

>>> bytes.__base__
<type 'basestring'>
>>> bytearray.__base__
<type 'object'>
但是,

>>> buf = bytearray()
>>> isinstance(buf, basestring)
False
以上代码是在Python2.7下测试的

不幸的是,在Python3.4下,它们是相同的

>>> bytes.__base__
<class 'object'>
>>> bytearray.__base__
<class 'object'>
>>字节。\u__
>>>拜蒂雷基地__

这里有几种方法可以使用

鸭子打字 由于Python是,您可以简单地执行以下操作(这似乎是通常建议的方式):

但是,您可以使用您描述的hasattr
,这样可能就可以了。当然,这是假设给定对象的
.decode()
方法返回字符串,并且没有令人讨厌的副作用

我个人推荐exception或
hasattr
方法,但使用什么取决于您

使用str() 这种方法不常见,但也有可能:

data = str(data, "utf-8")
其他编码是允许的,就像缓冲协议的
.decode()
一样。您还可以传递第三个参数来指定错误处理

单一分派通用函数(Python 3.4+) Python3.4及以上版本包括一个称为单分派通用函数的漂亮特性,通过。这有点冗长,但也更明确:

def func(data):
    # This is the generic implementation
    data = data.decode()
    ...

@func.register(str)
def _(data):
    # data will already be a string
    ...
如果您愿意,还可以为
bytearray
bytes
对象创建特殊处理程序


注意:单个分派函数只对第一个参数有效!这是一项有意的功能,请参阅。

除非您知道我们不知道的内容,否则此代码不正确:

if isinstance(data, bytes):
    data = data.decode()
您(似乎)不知道
数据的编码。你是在假设,但那很可能是错误的。由于您不知道编码。你有字节,在太阳底下可能有任何意义

好消息是,大多数随机字节序列都不是有效的UTF-8,因此当UTF-8中断时,它会大声中断(
errors='strict'
是默认值),而不是默默地做错误的事情。更好的消息是,大多数碰巧是有效的UTF-8的随机序列也是有效的ASCII码,每个人都同意如何解析

坏消息是没有合理的方法来解决这个问题。提供编码信息有一种标准方法:使用
str
而不是
字节
。如果某个第三方代码在没有任何上下文或信息的情况下将
bytes
bytearray
对象交给了您,那么唯一正确的操作就是失败


现在,假设您知道编码,您可以在此处使用
functools.singledispatch

@functools.singledispatch
def foo(data, other_arguments, ...):
    raise TypeError('Unknown type: '+repr(type(data)))

@foo.register(str)
def _(data, other_arguments, ...):
    # data is a str

@foo.register(bytes)
@foo.register(bytearray)
def _(data, other_arguments, ...):
    data = data.decode('encoding')
    # explicit is better than implicit; don't leave the encoding out for UTF-8
    return foo(data, other_arguments, ...)

这在方法上不起作用,
data
必须是第一个参数。如果这些限制不适用于您,请使用其他答案之一。

这取决于您想要解决的问题。如果希望使用相同的代码将两种情况转换为字符串,只需先将类型转换为
字节
,然后解码即可。这样,它是一个单行程序:

#!python3

b1 = b'123456'
b2 = bytearray(b'123456')

print(type(b1))
print(type(b2))

s1 = bytes(b1).decode('utf-8')
s2 = bytes(b2).decode('utf-8')

print(s1)
print(s2)
这样,您的答案可能是:

data = bytes(data).decode()

无论如何,如果您不想节省一些字节,我建议显式地将
'utf-8'
写入解码器。原因是下次您或其他人阅读源代码时,情况会更加明显。

这里有两个问题,答案不同

第一个问题,这篇文章的标题,是确定对象是否是Python中类似字节的对象的正确方法是什么?这包括许多内置类型(
字节
字节数组
数组.数组
内存视图
,其他?)以及用户定义的类型。我所知道的检查这些内容的最佳方法是尝试从它们中创建一个
memoryview

>>> memoryview(b"foo")
<memory at 0x7f7c43a70888>
>>> memoryview(u"foo")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: memoryview: a bytes-like object is required, not 'str'
记忆视图(b“foo”) >>>记忆视图(u“foo”) 回溯(最近一次呼叫最后一次): 文件“”,第1行,在 TypeError:memoryview:需要类似字节的对象,而不是“str”
不过,在原始帖子的正文中,问题似乎是如何测试对象是否支持decode()@伊丽莎白·迈尔斯(elizabeth myers)对这个问题的上述回答非常好请注意,并非所有类似字节的对象都支持decode() >>>text=“你好” >>>类型(内容) >>>类型(文本) >>>类型(文本)为str 真的 >>>类型(内容)为字节 真的
在Python 2中,如果isinstance(数据,字节)或
如果type(数据)=字节等,则测试
不起作用,在Python 2中,一个简单的ASCII字符串通过测试!由于我同时使用Python 2和Python 3,为了克服这一问题,我进行了以下检查:

if str(type(data)).find("bytes") != -1: print("It's <bytes>")
if str(type(data)).find(“bytes”)!=-1:打印(“它的”)

虽然有点难看,但它确实起到了问题所要求的作用,而且它总是以最简单的方式工作。

就个人而言,我和下一个家伙一样喜欢python的duck类型。但是,如果您需要检查输入参数并强制输入不同的类型,那么您就不再是duck类型,而是使代码更难阅读和维护。我在这里的建议(其他人可能不同意)是创建多个函数(处理类型强制并委托给一个基本实现)。(1)除非您需要它以兼容旧式Python 2代码;避免同时接受文本和二进制数据。如果您的函数使用文本,那么它应该只接受
str
。其他一些代码应该在输入时尽快从字节转换为Unicode。(2) “就像
>>> memoryview(b"foo")
<memory at 0x7f7c43a70888>
>>> memoryview(u"foo")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: memoryview: a bytes-like object is required, not 'str'
if str(type(data)).find("bytes") != -1: print("It's <bytes>")