Python의 배열-숫자 데이터를 효율적으로 사용하기 I

2024. 1. 30. 19:34python/intermediate

Python은 array표준 라이브러리에 덜 알려진 모듈 과 함께 제공되어 이진 데이터를 처리하는 데 도움이 될 수 있는 특수 시퀀스 유형을 제공합니다. 다른 시퀀스만큼 널리 사용되지 않거나 잘 문서화되어 있지 않기 때문에 array 모듈 사용과 관련하여 많은 오해가 있습니다. 이 튜토리얼을 읽고 나면 Python array모듈과 해당 모듈이 제공하는 해당 데이터 유형을 언제 사용해야 하는지에 대한 명확한 아이디어를 갖게 될 것입니다 .

프로그래밍의 배열 이해

컴퓨터 과학의 배열

배열을 더 잘 이해하려면 조금 축소하여 이론의 렌즈를 통해 살펴보는 것이 도움이 됩니다. 이를 통해 다음을 포함한 몇 가지 기본 용어가 명확해집니다.

  • 추상 데이터 유형
  • 데이터 구조
  • 데이터 유형

컴퓨터 과학은 요소 삽입이나 삭제와 같은 특정 작업을 지원하는 ADT(추상 데이터 유형) 로 데이터 컬렉션을 모델링합니다. 이러한 작업은 추상 데이터 유형의 고유한 동작을 설명하는 추가 제약 조건을 충족해야 합니다.

이 맥락에서 추상이라는 단어는 이러한 데이터 유형이 구현 세부 사항을 사용자에게 맡기고 ADT가 지원해야 하는 예상 의미 체계 또는 사용 가능한 작업 집합만 정의한다는 의미입니다. 결과적으로 데이터 구성에 대한 동일한 개념적 접근 방식을 구체적으로 구현한 몇 가지 대체 데이터 구조를 사용하여 하나의 추상 데이터 유형을 나타낼 수 있는 경우가 많습니다.

프로그래밍 언어는 일반적으로 사용자가 직접 구현할 필요가 없도록 편의를 위해 내장 데이터 형식의 형태로 몇 가지 데이터 구조를 제공합니다. 이는 매번 처음부터 시작하는 대신, 보다 추상적인 문제를 해결하는 데 집중할 수 있음을 의미합니다. 예를 들어, Python dict 데이터 유형은 사전 추상 데이터 유형을 구현하는 해시 테이블 데이터 구조 입니다 .

이러한 용어의 의미를 다시 말하면 추상 데이터 유형은 원하는 의미를 정의하고, 데이터 구조는 이를 구현하며, 데이터 유형은 프로그래밍 언어의 데이터 구조를 내장된 구문 구조로 나타냅니다.

추상 데이터 유형의 가장 일반적인 예는 다음과 같습니다.

  • Dictionaries
  • Graphs
  • Lists
  • Queues
  • Sets
  • Stacks
  • Trees

경우에 따라 추가 제약 조건을 통합하여 기존 ADT 위에 보다 구체적인 종류의 추상 데이터 유형을 구축할 수 있습니다. 예를 들어 대기열을 수정하거나 그 반대로 수정하여 스택을 구축할 수 있습니다.

보시다시피 ADT 목록에는 배열이 포함되어 있지 않습니다. 배열은 목록 추상 데이터 유형을 나타내는 특정 데이터 구조 이기 때문입니다. ADT 목록은 어레이가 지원해야 하는 작업과 표시해야 하는 동작을 나타냅니다. Python으로 작업해 본 적이 있다면 컴퓨터 과학의 list 목록이 무엇인지 이미 잘 알고 있을 것입니다.

참고:컴퓨터 과학의 list 목록 추상 데이터 유형과 전자를 나타내는 Python의 데이터 유형을 혼동하지 마십시오. 마찬가지로 이론적 배열 데이터 구조를 특정 배열 데이터 유형 으로 착각하기 쉽습니다. 많은 프로그래밍 언어는 구문에 내장된 편리한 기본 유형으로 제공합니다.

목록 추상 데이터 유형은 순서가 지정된 요소 시퀀스를 형성하는 선형 값 모음입니다. 이러한 요소는 특정 배열을 따릅니다. 즉, 각 요소는 일반적으로 0에서 시작하는 숫자 인덱스로 식별되는 다른 요소에 대한 상대적인 위치를 갖습니다. 목록에는 변수가 있지만 길이는 유한합니다. 여기에는 중복된 값뿐만 아니라 다양한 유형의 값이 포함될 수도 있고 포함되지 않을 수도 있습니다.

목록 추상 데이터 유형의 인터페이스는 일반적으로 다음 작업을 포함하는 Python의 list와 유사합니다.

ADT 나열파이썬의 list
인덱스로 요소 가져오기 fruits[0]
특정 인덱스에 요소 설정 fruits[0] = "banana"
주어진 인덱스에 요소 삽입 fruits.insert(0, "banana")
인덱스로 요소 삭제 fruits.pop(0),del fruits[0]
값으로 요소 삭제 fruits.remove("banana")
모든 요소 삭제 fruits.clear()
주어진 요소의 인덱스 찾기 fruits.index("banana")
오른쪽 끝에 요소 추가 fruits.append("banana")
다른 목록과 병합 fruits.extend(veggies),fruits + veggies
요소 정렬 fruits.sort()
요소 수를 가져옵니다. len(fruits)
요소 반복 iter(fruits)
요소가 있는지 확인 "banana" in fruits

데이터 구조로서의 배열

전통적인 배열 데이터 구조를 그래픽으로 시각화하려면 동일한 크기의 직사각형 상자가 나란히 늘어서 있고 각각 공통 유형의 고유한 값을 보유하고 있다고 상상해 보십시오. 예를 들어 정수 배열은 다음과 같습니다.

 

이 배열에는 0부터 6까지 인덱싱된 7개의 요소가 있으며 모두 정수입니다. 이러한 값 중 일부는 두 번 이상 발생합니다.

언뜻 보면 이는 Python의 표준 list와 비슷해 보입니다. 결국 둘 다 앞서 다룬 목록 추상 데이터 유형을 나타냅니다. 배열 데이터 구조를 특별하게 만드는 것은 몇 가지 고유한 기능입니다. 특히 배열은 다음과 같아야 합니다.

  • 동종: 배열의 모든 요소는 공통 데이터 유형을 공유하므로 균일한 크기를 가질 수 있습니다. 이는 혼합 유형의 요소를 포함할 수 있는 Python 목록과 다릅니다.
  • 연속적: 배열 요소는 컴퓨터 메모리에서 서로 인접해 있으며 연속적인 메모리 공간 블록을 차지합니다. 배열의 시작과 끝 사이에는 다른 데이터가 허용되지 않습니다. 이러한 레이아웃은 컴퓨터 메모리가 논리적으로 구성되는 방식에 해당합니다.
  • 고정 크기: 어레이가 차지하는 메모리 블록 바로 뒤에 다른 데이터가 올 수 있으므로 블록을 확장하면 해당 데이터를 덮어쓰게 되어 잠재적으로 심각한 오류나 오작동이 발생할 수 있습니다. 따라서 배열에 메모리를 할당할 때 나중에 변경할 수 없도록 크기를 미리 알아야 합니다.

처음 두 특성은 배열을 무작위 액세스 데이터 구조로 만들어 전체 배열을 순회하지 않고도 특정 인덱스에서 요소를 즉시 검색할 수 있게 해줍니다. 배열의 첫 번째 요소의 메모리 주소를 알면 간단한 수학 공식을 적용하여 원하는 요소의 주소를 계산할 수 있습니다.

 

배열의 인덱스 i 에 위치한 요소의 메모리 주소 A i 를 찾으려면 인덱스 0에 있는 첫 번째 요소 A 0 의 주소와 동일한 배열의 주소를 가져온 다음 오프셋을 추가할 수 있습니다. 모든 요소의 크기가 동일하므로 대상 인덱스 i 에 단일 요소의 크기(바이트)를 곱하여 메모리 주소 오프셋을 얻을 수 있습니다 .

이 공식은 모든 요소의 크기가 동일하고 서로 옆에 표시되는 한 작동합니다. 이러한 메모리 레이아웃의 단점은 배열의 고정 크기 입니다 . 이는 요소를 추가, 삽입 또는 제거하려는 경우에 분명해집니다. 그러나 다른 배열을 만들고, 기존 요소를 여기에 복사하고, 이전 배열을 무시하는 방식으로만 크기 조정을 시뮬레이션할 수 있습니다.

결과적으로 운영 체제에 더 큰 메모리 블록을 자주 요청하게 되고 데이터를 한 위치에서 다른 위치로 이동하는 데 시간을 낭비하게 됩니다. 이것이 순수 배열의 삽입과 삭제를 비효율적으로 만드는 이유입니다.

이 제한을 완화하는 한 가지 방법은 필요한 것보다 더 많은 메모리를 적극적으로 할당하고 배열 용량에 대해 현재 요소 수를 추적하는 추상화를 배열 위에 구축하는 것입니다. 기본 배열이 가득 차면 데이터를 더 큰 배열에 재할당하고 복사할 수 있습니다. 이는 동적 크기 조정에 대처하기 위해 Python list가 표면 아래에서 수행하는 작업과 대략 비슷합니다.

문자열과 같이 유형은 동일하지만 크기가 가변적인 요소는 어떻습니까?

문자열은 컴퓨터 메모리에서 여러 가지 표현을 가질 수 있습니다. 예를 들어 길이 접두사가 붙은 표현은 뒤에 오는 문자 수를 인코딩하기 위해 추가 바이트를 할당합니다. 또 다른 널리 사용되는 표현은 null로 끝나는 문자열 입니다. 이는 본질적으로 null 문자 라고 하는 특수 센티널 값 으로 끝나는 바이트 배열입니다 . 이러한 표현을 사용하면 문자열에 대한 포인터 배열을 만들 수 있습니다 .

 

 

 

위에 묘사된 배열은 포인터 또는 숫자 주소로 구성되며, 각각은 주어진 문자열이 시작되는 특정 메모리 영역을 나타냅니다. 개별 요소는 다양한 크기를 가질 수 있고 컴퓨터 메모리 전체에 분산되어 있을 수 있지만 해당 포인터는 배열에 맞는 균일한 크기의 일반 정수입니다.

알고 보니 배열 데이터 구조가 목록 추상 데이터 유형을 구현하는 유일한 방법은 아닙니다. 다음으로, 널리 사용되는 대안인 연결 목록에 대해 알아봅니다.

배열과 연결 목록

이 시점에서 여러분은 컴퓨터 과학의 목록이 추상적인 데이터 유형이고 배열이 특정 구현 중 하나라는 것을 알고 있습니다. 그런데 왜 둘 이상의 구현을 원하며 어떤 구현을 사용할지 어떻게 알 수 있습니까?

주어진 데이터 구조의 선택은 성능 과 메모리 효율성 에 매우 중요합니다 . 대부분의 데이터 구조는 둘 사이의 균형을 제공하며 일반적 으로 다른 작업을 희생하여 특정 작업에 대해 더 나은 시간 공간 복잡성을 제공합니다. 따라서 항상 해결하려는 특정 문제의 요구 사항에 따라 적합한 데이터 구조를 선택해야 합니다.

예를 들어, 배열 이나 연결 목록을 사용하여 목록 추상 데이터 유형을 구현할 수 있습니다 . 둘 다 요소의 시퀀스이지만 자주 조회하는 시나리오에는 배열이 더 적합하고, 삽입 또는 삭제 횟수가 더 많을 것으로 예상되면 연결 목록이 더 잘 작동합니다.

배열은 항상 임의 요소에 대한 즉각적인 액세스를 제공하지만 새 요소를 추가하려면 추가 시간이 필요합니다. 반대로 연결된 목록을 사용하면 빠르게 삽입할 수 있지만 인덱스로 요소를 찾는 데 시간이 더 오래 걸릴 수 있습니다. 이러한 절충안은 두 데이터 구조가 메모리에서 데이터를 구성하는 방식의 결과입니다.

Python의 배열(arrays)

Python의 list는 목록 추상 데이터 유형을 나타내지만 그 구현은 일반적인 배열이나 연결 목록이 아닙니다. CPython 소스 코드를 보면 기본이 객체에 대한 동적 포인터 배열 PyListObject이라는 것을 알 수 있으며 , 이를 통해 Python의 list는 두 데이터 구조의 이점을 결합할 수 있습니다. 영리하게 최적화되어 대부분의 상황에서 빠른 조회와 삽입을 보장합니다.

Python은 이전에 설명했던 문자열에 대한 포인터 배열을 유지하는 아이디어를 한 단계 더 발전시킵니다. 내부 배열에서 가리키는 값의 데이터 유형에 대한 추가 정보를 유지함으로써 이를 수행합니다.

이로 인해 Python의 list는 임의 유형의 이종 요소를 저장할 수 있습니다. 반면에, 이와 같은 과잉 할당으로 인해 Python의 list는 C와 같은 하위 수준 프로그래밍 언어에서 일반적으로 볼 수 있는 클래식 배열보다 메모리 효율성이 떨어 집니다.

요약하자면 Python은 내부적으로 배열 데이터 구조에 의존하지만 이를 사용자에게 직접 노출하지는 않습니다. Python에서 배열에 가장 가까운 방법은 표준 라이브러리 array또는 NumPy의 ndarray 데이터 유형을 사용하는 것입니다. 그러나 둘 중 어느 것도 숫자 값만 보유할 수 있으므로 실제 배열을 제공하지 않습니다.

Python array모듈 알아보기

참조 문서에 따르면 Python의 array모듈은 요소가 소수의 숫자 유형으로 제한되는 효율적인 배열 데이터 구조를 정의합니다. 따라서 이 모듈을 사용하여 문자열이나 사용자 정의 개체와 같은 임의 데이터 유형의 일반 배열을 생성할 수 없습니다. 하지만 이를 통해 수행할 수 있는 작업은 고성능 숫자 처리를 위한 대규모 데이터 세트를 콤팩트하게 표현하는 것입니다.

물론 앞서 언급한 NumPy 라이브러리나 pandas 와 같이 Python에는 수치 계산을 위한 더 강력한 도구가 있습니다 . 대부분의 경우 복잡한 과학적 계산 과 다차원 데이터 처리에 더 적합합니다. 반면에 array 모듈은 Python과 함께 제공되며 항상 사용 가능하므로 타사 라이브러리를 설치할 수 없거나 설치하고 싶지 않을 때 가장 잘 작동합니다.

array 모듈의 또 다른 일반적인 사용 사례에는 파일이나 네트워크 소켓에서 얻을 수 있는 바이너리 데이터 처리가 포함됩니다. 이는 순수 Python에서 작업하기 어렵고 비효율적인 원시 바이트 위에 편리한 추상화를 제공합니다. 이 모듈은 상대적인 단순성과 C와의 상호 운용성 측면에서 정말 빛을 발합니다. 이에 대해서는 이 튜토리얼의 뒷부분에서 살펴보겠습니다.

여러분의 흥미를 끌기 위해 Python에서 배열을 생성하는 기본 구문은 다음과 같습니다.

array(typecode[, initializer])

모듈에서 array 클래스를 가져온 후, 최소한 array를 위한 배열의 유형 코드를 지정하고 선택적으로 초기화 값을 제공해야 합니다 . 예를 들어, 다음은 4개의 연속된 정수 배열을 생성합니다.

In [ ]:
from array import array
array("i", [1, 2, 3, 4])

배열 요소의 유형을 선택하세요

array 모듈 에서 array 클래스 인스턴스를 만들기 전, 첫 번째 단계는 해당 요소에 대한 공통 숫자 유형을 결정하는 것입니다. 모든 배열 요소는 동일한 고정 숫자 유형을 가져야 합니다. 잘 알려진 몇 가지 숫자 유형 중에서 한 번 선택하면 마음이 바뀔 수 없으므로 현명하게 선택하십시오. 숫자 유형에 따라 가능한 값의 범위가 결정되므로 해당 범위를 벗어나는 숫자는 배열에 저장할 수 없습니다.

임의 종류의 객체를 허용하는 Python의 list와 달리 Python의 array는 생성 시 정의된 정확한 숫자 유형에 맞는 숫자만 수용할 수 있습니다. 실제 비유를 사용하려면 Python의 list를 식료품점 계산대에 있는 컨베이어 벨트로 생각할 수 있습니다. 대조적으로, Python의 array는 특정 크기의 계란을 담기 위해 특별히 설계된 상자와 비슷합니다.

Python은 구문을 통해 비교적 적은 숫자 유형을 제공합니다.

  • 정수
  • 부동 소수점 숫자 -복소수

Python의 정수는 임의의 정밀도를 가지 므로 이론적으로 제한이 없습니다. 부동 소수점 숫자와 복소수에는 sys.float_info 상수에 정의된 엄격한 제한이 있습니다.

Python 표준 라이브러리에는 위에 나열된 기본 유형을 기반으로 구축된 분수 및 소수를 비롯한 보다 구체적인 유형도 함께 제공됩니다. 그 외에도 당신은 스스로입니다. Python에서 사용할 수 있는 숫자 유형은 대부분의 상위 수준 사용 사례를 포괄하지만 하위 수준 이진 데이터를 처리하기 시작할 때 몇 가지 문제에 직면할 수 있습니다.

이러한 문제를 해결하기 위해 array모듈은 숫자 범위에 대한 훨씬 더 세부적인 제어 기능을 제공합니다. 표준 Python에서는 사용할 수 없는 C 프로그래밍 언어의 숫자 유형을 노출합니다. 예를 들어, 이 모듈을 사용하여 긴 정수 또는 단정밀도 부동 소수점 배열을 선언할 수 있습니다 . 또한 순수 Python의 모든 숫자는 항상 부호가 있는 반면, 이러한 숫자를 signed 또는 unsigned로 지정할 수 있습니다 .

참고: 배열의 요소에 액세스하면 인터프리터는 기본 데이터 유형을 작업할 수 있는 상위 수준 Python 객체로 래핑합니다. 이를 boxing 이라고 하며 , unboxing은 반대 작업입니다.

array 모듈 에는 13개의 숫자 유형이 있으며, 각각은 단일 문자 유형 코드로 표시되며 , typecodes 변수에 액세스하여 이를 확인할 수 있습니다.

In [ ]:
import array
array.typecodes

대문자는 부호가 없는 숫자에 해당하고, 소문자는 부호가 있는 숫자를 나타냅니다. 구체적인 의미는 다음과 같습니다.

유형 코드C타입최소 크기(바이트)
b signed char 1
B unsigned char 1
h signed short 2
H unsigned short 2
i signed int 2
I unsigned int 2
l signed long 4
L unsigned long 4
q signed long long 8
Q unsigned long long 8
f float 4
d double 8
u wchar_t 2

보시다시피 부호 있는 특성과 부호 없는 특성으로 구성된 정수 쌍 5개, 일관되게 부호 있는 부동 소수점 유형 2개, Python 3.3부터 더 이상 사용되지 않는 와이드 문자 유형 1개가 있습니다.

더 많은 바이트를 할당할수록 표현할 수 있는 숫자의 범위가 더 커집니다. 예를 들어 a signed short에는 메모리에 2바이트 또는 16비트가 필요하며, 이는 -32,768에서 32,767 사이의 숫자 범위를 제공합니다. 부호가 없는 상대를 사용하면 음수를 나타내는 기능이 손실되지만 최대 65,535까지 양수를 얻을 수 있습니다. 즉, 표현 가능한 값의 범위가 위쪽으로 이동합니다.

일반적으로 바이트 수와 숫자 유형의 부호 여부를 알면 다음과 같은 최소값과 최대값을 찾을 수 있습니다.

In [ ]:
def get_range(num_bytes, signed=True):
    num_bits = num_bytes * 8
    if signed:
        return -2 ** (num_bits - 1), 2 ** (num_bits - 1) - 1
    else:
        return 0, (2 ** num_bits) - 1

get_range(num_bytes=2, signed=False)
In [ ]:
get_range(num_bytes=2, signed=True)
In [ ]:
get_range(num_bytes=4, signed=False)
In [ ]:
get_range(num_bytes=4, signed=True)
In [ ]:
get_range(num_bytes=8, signed=False)
In [ ]:
get_range(num_bytes=8, signed=True)

결과 튜플은 각 숫자 범위에 포함된 최소값과 최대값을 나타냅니다.

앞서 본 표는 각 데이터 유형의 값을 저장하는 데 필요한 최소 바이트 수를 나타냅니다. 실제로 시스템 아키텍처와 Python 인터프리터가 컴파일된 방식에 따라 실제 바이트 수는 더 높을 수 있습니다.

In [ ]:
from array import array
array("i").itemsize
In [ ]:
array("i").typecode

구체적인 배열의 .itemsize속성을 확인하여 해당 요소 중 하나가 메모리에서 소비하는 바이트 수를 정확히 확인할 수 있습니다. 마찬가지로, 배열의 .typecode속성을 읽어 해당 배열을 만드는 데 사용한 문자를 표시할 수 있습니다. 두 속성 모두 읽기 전용입니다.

참고: array 클래스는 둘러싸는 모듈과 이름을 공유하므로 혼동될 수 있습니다. 이 튜토리얼에서는 정규화된 이름array.array를 사용하지 않고 Python array 배열을 참조합니다 . 클래스 외에 다른 것을 가져올 필요가 없는 한 이 from array import array 명령문을 사용하면 클래스 이름 앞에 모듈 이름이 붙는 것을 피할 수 있습니다.

외부 소스의 데이터를 배열로 로드하는 경우 해당 형식과 정확히 일치하는 유형을 선택해야 합니다. 때로는 비표준 숫자 유형을 array 모듈의 유형 코드 중 하나에 매핑하는 것이 불가능할 수도 있습니다. 예를 들어 OpenEXR 파일은 종종 16비트 부동 소수점 숫자를 사용하는 반면, 일부 WAV 파일은 24비트 부호 있는 정수를 사용하여 데이터를 인코딩합니다 . 나중에 그러한 상황에 대처하는 방법을 배우게 될 것입니다.

그렇지 않고 자신의 데이터를 쓰는 경우 가능한 모든 값에 맞는 가장 작은 유형을 사용하여 메모리 사용을 최적화하십시오. 0에서 200까지의 연령 배열이 있다고 가정해 보겠습니다. 연령은 음수일 수 없으므로 0에서 255까지의 값을 보유할 수 있는 부호 없는 바이트에 해당하는 유형 코드를 선택하여 충분한 공간을 확보할 수 있습니다.

요구 사항에 가장 적합한 숫자 유형을 결정한 후에는 최종적으로 배열을 만들 수 있습니다.

나중에 채울 빈 배열 만들기

배열의 생성자에는 원하는 요소 유형을 지정해야 하는 필수 인수가 하나만 필요합니다. 선택적 두 번째 인수를 생략하면 빈 숫자 배열을 정의하게 됩니다. 예를 들어, 다음 코드는 부호가 없는 2바이트 정수인 부호 없는 short의 빈 배열을 만듭니다.

In [ ]:
from array import array
empty = array("H")
len(empty)

길이가 고정된 전통적인 배열 데이터 구조와 달리 Python의 array 데이터 유형은 동적으로 크기가 지정 됩니다. 따라서 나중에 빈 배열에 요소를 추가하면 그에 따라 자동으로 크기가 조정됩니다.

기존 배열을 숫자로 채우는 방법을 배우기 전에 Python에서 배열 인스턴스를 만드는 다른 방법을 살펴보겠습니다.

다른 Iterable을 사용하여 새 배열 초기화

빈 배열을 만드는 대신 생성자에 두 번째 인수로 전달된 초기화 값 의 요소로 새 배열을 채울 수도 있습니다. 초기화 프로그램은 다음 유형 중 하나로 구성된 경우 bytes인스턴스이거나 iterable 이어야 합니다.

  • Integers
  • Floats
  • Characters

다른 프로그래밍 언어와 달리 Python에는 개별 문자를 나타내는 전용 유형이 없습니다. 반복 가능한 문자는 Python 문자열 또는 길이가 1인 문자열로 구성된 다른 컬렉션을 의미합니다. 또한 Python 배열은 언어의 또 다른 숫자 유형이더라도 복소수를 지원하지 않습니다.

다음은 Python 배열을 사용하여 동일한 바이트 시퀀스를 다양한 방식으로 해석하는 방법을 보여주는 몇 가지 예입니다. 예를 들어, 이를 통해 파일에서 이진 데이터를 읽는 방법을 제어할 수 있습니다. 이를 테스트하려면 snake emoji를 UTF-8로 인코딩하여 샘플 바이트를 생성하세요.

In [ ]:
snake_emoji = "\N{snake}".encode("utf-8")

snake_emoji
In [ ]:
len(snake_emoji)
In [ ]:
for byte in snake_emoji:
    print(format(byte, "b"))

결과 바이트 시퀀스는 4바이트로 구성되며, 해당 비트는 위의 코드 블록에 표시되어 있습니다. 이 바이트 시퀀스를 초기화 값으로 새 배열에 전달할 수 있습니다. 배열의 유형 코드에 따라 매우 다른 결과를 얻을 수 있습니다.

In [ ]:
array("b", snake_emoji)
In [ ]:
array("B", snake_emoji)
In [ ]:
array("h", snake_emoji)
In [ ]:
array("H", snake_emoji)
In [ ]:
array("i", snake_emoji)
In [ ]:
array("I", snake_emoji)
In [ ]:
array("f", snake_emoji)

유형 코드 b 또는 B를 사용하여 바이트 배열을 선언하면 이니셜라이저의 개별 바이트 값에 해당하는 정확히 4개의 숫자로 구성된 새 배열을 얻게 됩니다. 2바이트 short 또는 4바이트 정수 및 부동 소수점과 같은 더 넓은 유형을 사용하면 배열의 요소 수가 줄어들지만 크기는 더 커집니다.

추가적으로, 소문자 코드로 표시된 부호 있는 유형의 배열은 Python이 숫자를 음수로 해석하게 만듭니다. 이 경우 초기화 매개변수의 4바이트 모두 최상위 비트가 1로 설정되어 부호 비트가 됩니다 .

정수, 부동 소수점 또는 문자로 구성된 또 다른 반복 가능한 컨테이너가 이미 있는 경우 이를 배열의 생성자에 전달하여 해당 값으로 배열을 초기화할 수 있습니다.

In [ ]:
array("i", [2 ** i for i in range(8)])
In [ ]:
array("d", (1.4, 2.8, 4, 5.6))
In [ ]:
array("u", "café")
In [ ]:
array("u", ["c", "a", "f", "é"])

첫 번째 배열에는 8개의 정수가 포함되어 있으며 이는 목록 이해 에서 계산하는 2의 거듭제곱입니다 . 두 번째 배열에는 숫자 튜플 에서 파생된 4개의 배정밀도 부동 소수점 숫자가 있습니다 . 마지막 두 배열은 각각 문자열과 개별 단일 문자 문자열 목록에서 얻은 동일한 문자를 나타냅니다.

내부적으로 각 Python 배열은 숫자의 선형 모음입니다. 비어 있지 않은 배열의 텍스트 표현은 대신 Python 문자열로 렌더링되는 유니코드 문자 시퀀스를 제외하고 해당 숫자를 나타냅니다 . 그럼에도 불구하고 문자는 즉시 표시되지 않더라도 내부적으로 숫자 코드 포인트 로 인코딩됩니다.

필요에 따라 다양한 방법으로 Python 배열을 초기화할 수 있습니다. 또한 기존 어레이를 복제할 수 있으므로 원래 어레이에 영향을 주지 않고 데이터 복사본으로 작업할 수 있습니다.

In [ ]:
출처 : https://realpython.com/python-array/