Better Way3. bytes와 str의 차이를 알아둬라.
Bytes와 str의 차이
Python3 에서는 bytes와 str 두 가지 타입으로 문자 시퀀스를 나타낸다.
Bytes 인스턴스
- bytes 인스턴스는 부호가 없는 8바이트 데이터가 그대로 들어가며, 종종 아스키 인코딩을 사용해 내부 문자를 표시한다.
- bytes 인스턴스에는 직접 대응하는 텍스트 인코딩이 없다.
- 이진 데이터를 유니코드 데이터로 변환하기 위해서는 bytes의 decode메서드를 호출해야한다.
a = b'h\x65llo'
print(list(a))
print(a)
>>>
[104, 101, 108, 108, 111]
b'hello'
str 인스턴스
- str 인스턴스는 사람이 사용하는 언어의 문자를 표현하는 유니코드 코드 포인트가 들어있다.
- str인스턴스에는 직접 대응하는 이진 인코딩이 없다.
- 유니코드 데이터를 이진 데이터로 변환하기 위해서는 str의 encode메서드를 호출해야 한다.
a = 'a\u0300 propos'
print(list(a))
print(a)
>>>
['a', '`', ' ', 'p', 'r', 'o', 'p', 'o', 's']
à propos
유니코드 샌드위치
파이썬 프로그램을 작성할 때 유니코드 데이터를 인코딩하거나 디코딩하는 부분을 인터페이스의 가장 먼 경계지점에 위치시키는 유니코드 샌드위치라는 방식을 사용하는 것이 좋다. 유니코드 샌드위치를 간략하게 설명하자면
- 프로그램의 핵심 부분은 유니코드 데이터가 들어가 있는 str을 사용해야하고, 문자 인코딩에 대해 어떠한 가정도 하지 않는다.
- 결론적으로 다양한 텍스트 인코딩으로 입력 데이터를 받아들이고, 출력 텍스트 인코딩은 한 가지로(UTF-8) 엄격히 제한한다.
문자를 표현하는 타입이 둘로 나뉘어 있기 때문에 파이썬 코드에서는 아래와 같은 두 가지 상황이 자주 발생한다.
- UTF-8(또는 다른 인코딩 방식)로 인코딩된 8비트 시퀀스를 그대로 사용하고 싶다.
- 특정 인코딩을 지정하지 않은 유니코드 문자열을 사용하긷도 한다.
이를 위해 두가지 도우미 함수를 사용하기도 한다.
- bytes나 str 인스턴스를 받아서 항상 str인스턴스를 반환한다.
def to_str(bytes_or_str):
if isinstance(bytes_or_str, bytes):
value = bytes_or_str.decode("utf-8)
else:
value = bytes_or_str
return value
print(repr(to_str(b"foo")))
print(repr(to_str("bar")))
print(repr(to_str(b"\xed\x95\x9c")))
>>>
"foo"
"bar"
"한"
- bytes나 str 인스턴스를 받아서 항상 bytes를 반환한다.
def to_bytes(bytes_or_str):
if isinstance(bytes_or_str, str):
value = bytes_or_str.encode("utf-8")
else:
value = bytes_or_str
return value
print(repr(to_bytes(b"foo")))
print(repr(to_bytes("bar")))
print(repr(to_bytes("한글")))
>>>
b'foo'
b'bar'
b'\xed\x95\x9c\xea\xb8\x80'
bytes와 str의 호환성
이진 8비트 값과 유니코드 문자열을 파이썬에서 다룰 때 꼭 기억해야 할 두 가지 문제점이 있다.
- bytes와 str이 똑같이 작동하는 것 처럼 보이지만 각각의 인스턴스는 서로 호환되지 않기 때문에 전달 중인 문자 시퀀스가 어떤 타입인지 항상 잘 알고 있어야 한다는 점이다.
- 내장함수인 open을 호출해 얻은 파일 핸들과 관련된 연산들이 디폴트로 유니코드 문자열을 요구하고 이진 바이트 문자열을 요구하지 않는다는 것이다.
기억해야 할 내용
- bytes에는 8비트 값의 시퀀스가 들어 있고, str에는 유니코드 코드 포인트의 시퀀스가 들어있다.
- 처리할 입력이 원하는 문자 시퀀스(8비트 값, UTF-8로 인코딩된 문자열, 유니코드 코드 포인트들)인지 확실히 하려면 도우미 함수를 사용하라.
- bytes와 str 인스턴스를 (>, ==, +, % 와 같은) 연산자에 섞어서 사용할 수 없다.
- 이진 데이터를 파일에서 읽거나 파일에 쓰고 싶으면 항상 이진 모드(rb 나 wb)로 파일을 열어라
- 유니코드 데이터를 파일에서 읽거나 파일에 쓰고 싶을 때는 시스템 디폴트 인코딩에 주의하라. 인코딩 차이로 놀라고 싶지 않으면 open에 encoding 파라미터를 명시적으로 전달하라.
질문
repr() 함수란?
- str() 함수는 사용자가 보기 쉬운 형태로 보여줄 때 사용되고, repr() 함수는 시스템이 해당 객체를 인식할 수 있는 공식적인 문자열로 나타내 줄 때 사용한다.
- print함수가 무조건 str로 표현하기 때문에 repr함수를 입혀서 str이나 byte형태 있는 그대로 출력하게 해준다.
- 디버깅 출력에도 종종 사용된다.
유니코드란?
- 사람의 언어를 세계 공통으로 정리한 코드. 즉, 전 세계에서 일관되게 표현하고 다룰 수 있도록 설계된 산업 표준