Batter way03

매일 공부(ML)·2022년 2월 1일
0

문자열 데이터의 시퀀스 표현

bytes

  • 이런 유형의 인스턴스는 부호가 없는 8바이트 데이터가 그대로 들어간다.

  • 아스키 인코딩을 사용해 내부 문자 표시

  • 직접 대응하는 텍스트 인코딩이 없다

  • 이진 데이터를 유니코드 데이터로 변환(decode메서드 호출)

*예시1

a = b'h\x64llo'
print(list(a)) #[104, 101, 108, 108, 111]
print(a) # b'hello'

*예시2

# bytes or 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 #bytes 인스턴스
    
print(repr(to_bytes(b'foo'))) # b'foo'
print(repr(to_bytes('bar'))) # b'bar'
print(repr(to_bytes('한글'))) # b'\xed\x95\x9c\xea\xb8\x80'
  • bytes인스턴스끼리는 더하거나 비교 가능
print(b'one'+b'two') # b'onetwo'

assert b'red' > b'blue'

str

  • 이런 유형의 인스턴스는 언어의 문자를 표현하는 유니코드 코드 포인트가 있다.

  • 직접적으로 대응하는 텍스트 인코딩이 있다

  • 유니코드 데이터를 이진 데이터로 변환(encode 메서드 호출)

*예시1

a = 'a\u0300 propors'
print(list(a)) # ['a', '`', ' ', 'p', 'r', 'o', 'p', 'o','s']
print(a) #a` propos

*예시2


# bytes or 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 #str 인스턴스
    
print(repr(to_str(b'foo'))) # 'foo'
print(repr(to_str('bar'))) # 'bar'
print(repr(to_str(b'\wed\x95\x9c'))) # UTF-8에서 한글은 3바이트입니다., '한'
  • str인스턴스끼리는 더하거나 비교 가능
print('one' + 'two')
assert 'red' > 'blue'

참고

시스템 디폴트 인코딩 방식(UTF-8)
  • 유니코드 샌드위치: 유니코드 데이터를 인코딩 혹은 디코딩하는 부분을 인터페이스의 가장 먼 경계 지점에 위치

  • str사용

  • 문자 인코딩에 대해 가정하면 안됨

  • 다양한 텍스트 인코딩(Latin-1, Shift JIS, euc-kr, cp949, Big5등)으로 입력데이터 받기

  • 출력 인코딩은 UTF-8으로만 제한된다.

  • bytes와 str이 각각의 인스턴스는 서로 호환되지 않는다.(데이터 타입 다를 시 연산 안되는 것처럼 이것도 그렇다,)

  • 문자 시퀀스가 어떤 타입인지 항상 잘 알고 있어야 한다.

  • bytes와 str인스턴스가 같은지 비교 시 항상 False가 나온다

  • %연산자는 각 타입의 형식화 문자열에 대해 작동한다.

  • str인스턴스를 bytes 형식화 문자열에 넘길 수는 없다.

  • bytes인스턴스를 str 형식화 문자열에는 넘길 수 있다.

print('red %s' % b'blue') #red b'blue'

문자를 표현하는 타입이 둘로 남겨져서 생기는 상황

  • UTF-8로 인코딩된 8비트 시퀀스를 그대로 사용

  • 특정 인코딩을 지정하지 않은 유니코드 문자열 사용

파일 핸들과 관련한 연산들이 디폴트 요구의 차이(유니코드O,이진 바이트x)

  • 파일 핸들: 내장 함수인 open을 호출해서 얻음

  • 코드 실행이 안됨

    • 이유: 이진 쓰기 모드('wb')방식이 아닌 텍스트 쓰기 모드('w') 열기
  • 파일이 텍스트 모드

    • 유니코드 데이터가 있는 str인스턴스 요구
    • 'wb'모두 사용헤서 파일 열기
with open('data.bin', 'wb') as f:

    f.write(b'\xf1\xf2\xf3\xf4\xf5')
    
  • 파일 읽기
# open함수의 encoding파라미터 명시

with open('data.bin', 'rb') as f:

    data = f.read()
    
assert data == b'\xf1\xf2\xf3\xf4\xf5' #조건문
핵심 정리
  • bytes에는 8비트 값의 시퀀스이고, str에는 유니코드 코드 포인트의 시퀀스가 들어 있다.

  • 처리할 입려깅 원하는 문자 시퀀스인지 확실히 하려면 도우미 함수 사용

    • 8비트 값, UTF-8로 인코딩된 문자열, 유니코드 코드 포인트
  • bytes와 str 인스턴스를(>,==,+,%와 같은)연산자에 섞어서 사용X

  • 이진 데이터를 읽거나 쓸 때 이진 모드('rb' or 'wb')로 열기

  • 유니코드 데이터를 파일에서 읽거나 파일을 쓸 때, 시스템 디폴트 인코딩 주의

  • open encoding 파라미터를 명시적으로 전달하여 인코딩 차이로 놀라지 않게 된다.

profile
성장을 도울 아카이빙 블로그

0개의 댓글