문자열과 바이트 문자열의 차이점은 무엇입니까?


209

바이트 문자열을 반환하는 라이브러리로 작업 중이며 이것을 문자열로 변환해야합니다.

차이가 무엇인지 확실하지 않지만-있다면.

답변:


260

파이썬 3을 가정하면 (파이썬 2에서이 차이는 좀 덜 정의되어 있음) 문자열은 일련의 문자, 즉 유니 코드 코드 포인트입니다 . 이들은 추상적 개념이며 디스크에 직접 저장할 수 없습니다. 바이트 문자열은 디스크에 저장할 있는 바이트 시퀀스입니다 . 그들 사이의 매핑은 인코딩입니다 . 많은 것들이 있습니다 (그리고 무한히 많은 것들이 가능합니다)-다른 인코딩이 동일한 바이트를 매핑 할 수 있기 때문에 변환을 수행하기 위해 특정 경우에 적용되는 것을 알아야합니다 다른 문자열로 :

>>> b'\xcf\x84o\xcf\x81\xce\xbdo\xcf\x82'.decode('utf-16')
'蓏콯캁澽苏'
>>> b'\xcf\x84o\xcf\x81\xce\xbdo\xcf\x82'.decode('utf-8')
'τoρνoς'

사용할 것을 알고 나면 .decode()바이트 문자열 의 메소드를 사용하여 위와 같이 올바른 문자열을 얻을 수 있습니다. 완전성을 위해 .encode()문자열 의 방법은 반대 방향으로 진행됩니다.

>>> 'τoρνoς'.encode('utf-8')
b'\xcf\x84o\xcf\x81\xce\xbdo\xcf\x82'

7
Python 2 사용자를 명확히하기 위해 str유형은 유형과 동일 bytes합니다. 이 답변은 unicode유형 (파이썬 3에는 존재하지 않음) 과 유형을 동등하게 비교합니다 str.
craymichael

3
@KshitijSaraogi 그것은 사실이 아닙니다. 그 전체 문장이 편집되었고 약간 불행합니다. Python 3 str객체 의 메모리 내 표현은 Python 측에서 액세스 할 수 없거나 관련이 없습니다. 데이터 구조는 일련의 코드 포인트입니다. 아래 PEP 393 , 정확한 내부 인코딩은 라틴 1, UCS2 또는 UCS4 중 하나이며, 처음 요청 후 UTF-8 표현은 캐시 할 수 있지만, 심지어 C 코드는 이러한 내부 세부 사항에 의존하지 않는 것이 좋습니다.
lvc

1
디스크에 직접 저장할 수 없다면 메모리에 어떻게 저장됩니까?
z33k

2
@orety 그들은 인코딩해야합니까 어떻게 든 바로 그 이유 때문에 내부적으로,하지만이 아닌 부동 소수점 숫자가 저장되는 방법에 대해 걱정하지 않아도 많은처럼 파이썬 코드에서 당신에게 expos3s.
lvc

1
@ChrisStryczynski는 위의 주석을 참조하십시오-그것들이 어떻게 든 메모리에 저장되어 있지만 그 형식은 명시 적으로 추상화되어 있습니다. 실제로 요즘 프로그램의 수명 기간 동안 변경되어 다른 문자열간에 다를 수 있으며 문자에 따라 두 개 이상 (일부 인코딩이 캐시 됨) 일 수도 있습니다.하지만 걱정해야 할 유일한 시간은 그것은 문자열 유형 자체의 구현을 해킹하는 경우입니다.
lvc

390

컴퓨터가 저장할 수있는 유일한 것은 바이트입니다.

컴퓨터에 무엇이든 저장하려면 먼저 인코딩 해야합니다 ( 예 : 바이트로 변환). 예를 들면 다음과 같습니다.

  • 음악을 저장하려면, 먼저 있어야 인코딩 사용하여 MP3, WAV
  • 당신이 사진을 저장하려면, 먼저 있어야 인코딩 사용하여 PNG, JPEG
  • 텍스트를 저장하려면, 먼저 있어야 인코딩 사용하여 ASCII, UTF-8

MP3, WAV, PNG, JPEG, ASCIIUTF-8의 예 인코딩 . 인코딩은 오디오, 이미지, 텍스트 등을 바이트 단위로 나타내는 형식입니다.

파이썬에서 바이트 문자열은 바이트 시퀀스입니다. 사람이 읽을 수 없습니다. 후드 아래에서 모든 것을 바이트 문자열로 변환해야 컴퓨터에 저장할 수 있습니다.

반면에 종종 "문자열"이라고하는 문자열은 일련의 문자입니다. 사람이 읽을 수 있습니다. 문자열은 컴퓨터에 직접 저장할 수 없으며 먼저 인코딩 해야합니다 (바이트 문자열로 변환). 문자열을 ASCIIand와 같은 바이트 문자열로 변환 할 수있는 여러 인코딩이 있습니다 UTF-8.

'I am a string'.encode('ASCII')

위의 Python 코드는 encoding을 사용하여 문자열 'I am a string'을 인코딩 ASCII합니다. 위 코드의 결과는 바이트 문자열입니다. 그것을 인쇄하면 파이썬은 그것을로 표시합니다 b'I am a string'. 그러나 바이트 문자열 은 사람이 읽을 수 없으며ASCII 인쇄 할 때 파이썬이 디코딩한다는 것만 기억하십시오 . Python에서 바이트 문자열은로 표시되고 b그 뒤에 바이트 문자열이 ASCII표시됩니다.

인코딩에 사용 된 인코딩을 알고 있으면 바이트 문자열을 문자열 로 다시 디코딩 할 수 있습니다 .

b'I am a string'.decode('ASCII')

위의 코드는 원래 문자열을 반환합니다 'I am a string'.

인코딩 및 디코딩은 역 연산입니다. 디스크에 쓰기 전에 모든 것을 인코딩해야하며, 사람이 읽을 수 있으려면 먼저 디코딩해야합니다.


59
Zenadix는 여기에 몇 가지 명성이 필요합니다. 이 환경에서 몇 년 동안 활동 한 후, 그는 저와 함께한 첫 번째 설명입니다. 다른 팔에 문신을 할 수도 있습니다 (한 팔에는 이미 Joel Spolsky의 유니 코드 및 문자 집합에 대해 반드시 알아야하는 절대적인 최소 모든 소프트웨어 개발자가 있습니다)
neil.millikin

4
절대적으로 훌륭합니다. 자명하고 이해하기 쉽다. 그러나 나는이 줄을 언급하고 싶습니다- "당신이 그것을 인쇄하면, 파이썬은 그것을 b'I am a string로 나타낼 것입니다."는 Python3의 경우와 마찬가지로 Python2 바이트와 str은 같은 것입니다.
SRC

5
이 주제에 대해 명확하게 설명하기 위해 사람이 읽을 수있는 설명을 제공하여이 현상금을 수여합니다.
fedorqui 'SO 중지 피해'

3
좋은 대답입니다. 역사적으로 프로그래머와 프로그래밍 언어는 바이트 시퀀스와 ASCII 문자열이 동일한 것으로 명시 적 또는 암시 적으로 가정하는 경향이 있음을 더 명확하게 지적하는 입니다. 파이썬 3은이 가정을 정확하게 깨뜨리기로 결정했습니다.
nekomatic

4
조엘의 게시물에 대한 링크 위에 @ neil.millikin 언급 : joelonsoftware.com/2003/10/08/...
Kshitij Saraogi에게

14

참고 : Python 2의 수명이 거의 다되었으므로 Python 3에 대한 답변을 더 자세히 설명하겠습니다.

파이썬 3에서

bytes8 비트 부호없는 값 str의 시퀀스로 구성되는 반면, 인간 언어의 텍스트 문자를 나타내는 유니 코드 코드 포인트의 시퀀스로 구성됩니다.

>>> # bytes
>>> b = b'h\x65llo'
>>> type(b)
<class 'bytes'>
>>> list(b)
[104, 101, 108, 108, 111]
>>> print(b)
b'hello'
>>>
>>> # str
>>> s = 'nai\u0308ve'
>>> type(s)
<class 'str'>
>>> list(s)
['n', 'a', 'i', '̈', 'v', 'e']
>>> print(s)
naïve

비록 bytesstr같은 방식으로 작동하는 것, 자신의 인스턴스 즉, 서로 호환되지 않습니다, bytes그리고 str인스턴스는 같은 통신 사업자와 함께 사용할 수 없습니다 >+. 또한 등호에 대한 비교 bytesstr인스턴스 (예 :)를 사용 하면 정확히 동일한 문자가 포함 된 경우에도 ==항상 평가됩니다 False.

>>> # concatenation
>>> b'hi' + b'bye' # this is possible
b'hibye'
>>> 'hi' + 'bye' # this is also possible
'hibye'
>>> b'hi' + 'bye' # this will fail
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can't concat str to bytes
>>> 'hi' + b'bye' # this will also fail
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can only concatenate str (not "bytes") to str
>>>
>>> # comparison
>>> b'red' > b'blue' # this is possible
True
>>> 'red'> 'blue' # this is also possible
True
>>> b'red' > 'blue' # you can't compare bytes with str
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: '>' not supported between instances of 'bytes' and 'str'
>>> 'red' > b'blue' # you can't compare str with bytes
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: '>' not supported between instances of 'str' and 'bytes'
>>> b'blue' == 'red' # equality between str and bytes always evaluates to False
False
>>> b'blue' == 'blue' # equality between str and bytes always evaluates to False
False

내장 함수를 사용하여 리턴 된 파일을 처리 할 때 bytes및 처리 할 때 또 다른 문제가 발생 합니다. 한편으로 파일에서 이진 데이터를 읽거나 쓰지 않으려면 항상 'rb'또는 'wb'와 같은 이진 모드를 사용하여 파일을여십시오. 반면에 파일에서 유니 코드 데이터를 읽거나 쓰려면 컴퓨터의 기본 인코딩을 알고 있으므로 필요에 따라 매개 변수를 전달하여 놀라움을 피하십시오.stropenencoding

파이썬 2에서

str8 비트 값 unicode시퀀스로 구성되는 반면 유니 코드 문자 시퀀스로 구성됩니다. 한 가지 유념해야 할 점은 인 str하고 unicode있는 경우 사업자와 함께 사용할 수있는 str단지는 7 비트 ASCI 문자로 구성되어 있습니다.

사이의 변환 도우미 기능을 사용하는 것이 유용 할 수 있습니다 strunicode파이썬 2, 사이 bytesstr파이썬 3.


4

에서 유니 코드 무엇입니까 :

기본적으로 컴퓨터는 숫자 만 처리합니다. 문자와 기타 문자를 각각 번호를 지정하여 저장합니다.

......

유니 코드는 플랫폼, 프로그램, 언어 및 언어에 관계없이 모든 문자에 고유 한 번호를 제공합니다.

따라서 컴퓨터가 문자열을 나타내는 경우 고유 한 유니 코드 번호를 통해 문자열의 컴퓨터에 저장된 문자를 찾고이 숫자는 메모리에 저장됩니다. 그러나 문자열은 디스크에 직접 쓰거나 고유 한 유니 코드 번호를 통해 네트워크에서 문자열을 전송할 수 없습니다.이 숫자는 단순한 십진수입니다. 문자열을와 같은 바이트 문자열로 인코딩해야합니다 UTF-8. UTF-8는 가능한 모든 문자를 인코딩 할 수있는 문자 인코딩이며 문자를 바이트로 저장합니다 ( 이것 처럼 보입니다 ). 따라서 인코딩 된 문자열 UTF-8은 거의 모든 곳에서 지원 되므로 어디에서나 사용할 수 있습니다 . 인코딩 된 텍스트 파일을 열면UTF-8다른 시스템에서는 컴퓨터가 고유 한 유니 코드 번호를 통해이를 해독하고 그 안에 문자를 표시합니다. 브라우저가 UTF-8네트워크에서 인코딩 된 문자열 데이터를 수신 하면 데이터를 문자열로 디코딩하고 (브라우저를 UTF-8인코딩 한 것으로 가정 ) 문자열을 표시합니다.

python3에서는 문자열과 바이트 문자열을 서로 변환 할 수 있습니다.

>>> print('中文'.encode('utf-8'))
b'\xe4\xb8\xad\xe6\x96\x87'
>>> print(b'\xe4\xb8\xad\xe6\x96\x87'.decode('utf-8'))
中文 

한마디로, 문자열은 사람이 컴퓨터에서 읽을 수 있도록 표시하기위한 것이고 바이트 문자열은 디스크와 데이터 전송에 저장하기위한 것입니다.


1

유니 코드는 문자 및 다양한 형식의 형식 (예 : 소문자 / 대문자, 줄 바꿈, 캐리지 리턴) 및 기타 "사물"(예 : 이모 지)의 이진 표현을 위해 합의 된 형식입니다. 컴퓨터는 ASCII 표현 (다른 일련의 비트) 또는 다른 표현 (비트 계열)을 저장하는 것보다 메모리 또는 파일에 상관없이 유니 코드 표현 (일련의 비트)을 저장할 수 없습니다. ).

들어 통신이 자리를 차지할, 통신의 당사자가 사용됩니다 어떤 표현에 동의해야합니다.

유니 코드는 인간 간 및 컴퓨터 간 통신에 사용되는 모든 가능한 문자 (및 기타 "사물") 를 나타내려고하기 때문에 다른 표현 시스템보다 많은 문자 (또는 사물)를 표현하기 위해 더 많은 비트가 필요합니다. 보다 제한된 문자 / 사물 집합을 나타내려고 노력하십시오. "간단 화"하고 아마도 과거 사용을 수용하기 위해, 유니 코드 표현은 파일에 문자를 저장하기 위해 거의 모든 다른 표현 시스템 (예 : ASCII)으로 변환됩니다.

그것은 유니 코드가있는 경우가 아니라 할 수없는 파일에 문자를 저장, 또는 통해 전송에 사용할 수 있는 단순히 것을, 통신 채널 이다 없습니다.

"문자열"이라는 용어는 정확하게 정의되지 않았습니다. 일반적인 사용법에서 "문자열"은 문자 / 사물 집합을 나타냅니다. 컴퓨터에서, 이들 문자는 많은 다른 비트 단위 표현 중 어느 하나에 저장 될 수있다. "바이트 문자열"은 8 비트 (8 비트는 바이트라고 함)를 사용하는 표현을 사용하여 저장된 문자 세트입니다. 요즘 컴퓨터는 유니 코드 시스템 (가변 바이트 수로 표시되는 문자)을 사용하여 문자를 메모리에 저장하고 바이트 문자열 (싱글 바이트로 표시되는 문자)을 사용하여 파일을 파일에 저장하므로 변환 된 문자를 표현하기 전에 사용해야합니다 메모리의 파일은 파일의 저장소로 이동합니다.


0

간단한 한 문자 문자열 'š'을 가지고 일련의 바이트로 인코딩 합시다 .

>>> 'š'.encode('utf-8')
b'\xc5\xa1'

이 예제의 목적을 위해 바이트 시퀀스를 이진 형식으로 표시하겠습니다.

>>> bin(int(b'\xc5\xa1'.hex(), 16))
'0b1100010110100001'

이제는 일반적으로 정보가 어떻게 인코딩되었는지 모른 채 정보를 해독 할 수 없습니다 . utf-8텍스트 인코딩이 사용 된 것을 알고있는 경우에만 utf-8 디코딩 알고리즘을 따라 원래 문자열을 얻을 수 있습니다.

11000101 10100001
   ^^^^^   ^^^^^^
   00101   100001

이진수를 101100001문자열로 다시 표시 할 수 있습니다 .

>>> chr(int('101100001', 2))
'š'

0

파이썬 언어는 포함 strbytes표준 "내장 유형". 다시 말해, 둘 다 클래스입니다. 왜 파이썬이 이런 식으로 구현되었는지 합리화하려고 노력하는 것이 가치가 있다고 생각하지 않습니다.

데 그렇게 말했다, str그리고 bytes서로 매우 유사합니다. 둘 다 동일한 방법을 공유합니다. 다음과 같은 메소드가 str클래스에 고유합니다 .

casefold
encode
format
format_map
isdecimal
isidentifier
isnumeric
isprintable

다음과 같은 메소드가 bytes클래스에 고유합니다 .

decode
fromhex
hex
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.