programing

파이썬에서 객체가 바이트와 같은 객체인지 확인하는 적절한 방법은 무엇입니까?

bestprogram 2023. 5. 22. 21:50

파이썬에서 객체가 바이트와 같은 객체인지 확인하는 적절한 방법은 무엇입니까?

나는 다음을 예상하는 코드를 가지고 있습니다.str할 것입니다.bytes다음과 같은 방법으로:

if isinstance(data, bytes):
    data = data.decode()

불행히도, 이것은 다음의 경우에는 작동하지 않습니다.bytearray개체가 다음 중 하나인지 테스트할 수 있는 더 일반적인 방법이 있습니까?bytes또는bytearray아니면 둘 다 확인해야 하나요?아이즈hasattr('decode')내가 느끼는 것만큼 나쁜가요?

여기서 사용할 수 있는 몇 가지 접근법이 있습니다.

오리 타이핑

Python은 오리 타입이기 때문에 다음과 같이 간단하게 할 수 있습니다(일반적으로 제안되는 방식인 것 같습니다).

try:
    data = data.decode()
except (UnicodeDecodeError, AttributeError):
    pass

사용할 수 있습니다.hasattr하지만 당신이 묘사한 것처럼, 그리고 아마 괜찮을 것입니다.론물, 이은같, 다과가다니정합을 한 것입니다.decode()지정된 개체에 대한 메서드는 문자열을 반환하며 심각한 부작용은 없습니다.

나 저는개예외나로를 합니다.hasattr방법, 하지만 당신이 사용하는 것은 당신에게 달려 있습니다.

str() 사용

이러한 접근 방식은 흔하지 않지만 가능합니다.

data = str(data, "utf-8")

버퍼 프로토콜과 마찬가지로 다른 인코딩도 허용됩니다..decode()세 번째 매개 변수를 전달하여 오류 처리를 지정할 수도 있습니다.

단일 발송 일반 기능(Python 3.4+)

Python 3.4 이상에는 functools.singledispatch를 통해 단일 디스패치 제네릭 함수라는 강력한 기능이 포함되어 있습니다.이것은 좀 더 장황하지만, 또한 더 명확합니다.

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

@func.register(str)
def _(data):
    # data will already be a string
    ...

다음을 위한 특수 핸들러를 만들 수도 있습니다.bytearray그리고.bytes개체를 선택할 수 있습니다.

주의: 단일 발송 기능은 첫 번째 인수에서만 작동합니다!이것은 의도적인 기능입니다. PEP 433을 참조하십시오.

사용할 수 있는 항목:

isinstance(data, (bytes, bytearray))

기본 클래스가 다르기 때문에 여기에서 사용됩니다.

>>> bytes.__base__
<type 'basestring'>
>>> bytearray.__base__
<type 'object'>

확기하를 확인하는 bytes

>>> by = bytes()
>>> isinstance(by, basestring)
True

하지만,

>>> buf = bytearray()
>>> isinstance(buf, basestring)
False

위의 코드는 python 2.7에 따라 테스트됩니다.

불행하게도, python 3.4에서는 동일합니다.

>>> bytes.__base__
<class 'object'>
>>> bytearray.__base__
<class 'object'>
>>> content = b"hello"
>>> text = "hello"
>>> type(content)
<class 'bytes'>
>>> type(text)
<class 'str'>
>>> type(text) is str
True
>>> type(content) is bytes
True

이 코드는 사용자가 모르는 것을 알지 못하는 한 올바르지 않습니다.

if isinstance(data, bytes):
    data = data.decode()

다의인을모것같다의 .data당신은 그것이 UTF-8이라고 가정하고 있지만, 그것은 매우 틀릴 수 있습니다.인코딩을 모르기 때문에 텍스트가 없습니다.태양 아래서 어떤 의미를 가질 수 있는 바이트를 가지고 있습니다.

한 UTF-8이큰이라는 것입니다.errors='strict'(기본값)을 사용하여 조용히 잘못된 작업을 묵묵히 수행하는 대신.더 좋은 소식은 UTF-8이 유효한 대부분의 무작위 시퀀스도 유효한 ASCII이며, 어쨌든 구문 분석 방법에 대해 거의 모든 사람이 동의한다는 것입니다.

나쁜 소식은 이것을 고칠 수 있는 합리적인 방법이 없다는 것입니다.인코딩 정보를 제공하는 표준 방법은 다음과 같습니다.str대신에bytes어떤 타사 코드가 당신에게 전달한 경우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첫 번째 인수여야 합니다.이러한 제한이 적용되지 않으면 다른 대답 중 하나를 대신 사용합니다.

그것은 당신이 무엇을 해결하고 싶은지에 달려 있습니다.두 대소문자를 모두 문자열로 변환하는 동일한 코드를 사용하려면 유형을 다음으로 변환하면 됩니다.bytes먼저, 그 다음에 디코딩.이런 식으로, 그것은 한 줄기 선이 됩니다.

#!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에서 객체가 바이트와 같은 객체인지 확인하는 적절한 방법은 무엇입니까?여기에는 여러 가지 기본 제공 유형이 포함됩니다.bytes,bytearray,array.array,memoryview기타?) 및 사용자 정의 유형도 포함될 수 있습니다.이것들을 확인하는 가장 좋은 방법은 다음을 만드는 것입니다.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'

그러나 원본 게시물 본문에서 질문은 대신 객체가 디코드()를 지원하는지 여부를 테스트하는 방법에 대한 것으로 보입니다.@이 질문에 대한 위의 답변은 훌륭합니다.모든 바이트와 유사한 개체가 디코드()를 지원하는 것은 아닙니다.

시험은if isinstance(data, bytes)또는if type(data) == bytes등은 단순한 ASCII 문자열이 테스트를 통과하는 Python 2에서 작동하지 않습니다! 왜냐하면 저는 Python 2와 Python 3을 모두 사용하기 때문에 이것을 극복하기 위해 다음과 같은 검사를 합니다.

if str(type(data)).find("bytes") != -1: print("It's <bytes>")

좀 못생겼지만, 질문이 요구하는 을 하고 항상 가장 간단한 방법으로 작동합니다.


오랜만에...이것은 더 짧고, 더 단순하며, 더 "우아한" 것입니다.

if not type(data) == str: print("It's bytes")

언급URL : https://stackoverflow.com/questions/34869889/what-is-the-proper-way-to-determine-if-an-object-is-a-bytes-like-object-in-pytho