Python 구조체 구현

Updated:

Python은 C언어에서 사용하는 struct를 사용할 수 없습니다.

그래서 Python 에서는 몇가지 모듈을 이용하여 C 언어에있는 struct를 구현할 수 있는데요. structcollection 모듈을 이용해보겠습니다.

Struct

https://docs.python.org/2/library/struct.html 사이트에 나와있는 글을 보겠습니다.

이 모듈은 Python 값과 Python 문자열로 표시되는 C 구조체 사이의 변환을 수행합니다. 파일이나 네트워크 연결에서 저장된 이진 데이터를 처리하는 데 사용할 수 있습니다. C 구조체의 레이아웃과 파이썬 값과의 변환에 대한 간단한 설명으로 형식 문자열을 사용합니다.

Byte Order, Size, and Alignment

Chracter Byte order Size Alignment
@ native native native
= native standard none
< little-endian standard none
> big-endian standard none
! network(=big -endian) standard none

Character Format

Format C Type Python Type Standard Size Notes
x pad byte no value / /
c char string of length 1 1 /
b signed char interger 1 (3)
B unsigned char integer 1 (3)
? _Bool bool 1 (1)
h short integer 2 (3)
H iunsigned short integer 2 (3)
i int integer 4 (3)
I unsigned int integer 4 (3)
l long integer 4 (3)
L unsigned long integer 4 (3)
q long long integer 8 (2), (3)
f float float 4 (4)
d double float 8 (4)
s char[] string / /
p char[] string / /

Notes 에 대한 정확한 설명은 찾지 못했습니다. 추후 알게되면 업데이트 하겠습니다.

Examples

Pack, Little Endian, Big Endian

import struct

var = struct.pack('iii', 1, 2, 3)
littleVar = struct.pack('<iii', 1, 2, 3)
BigVar = struct.pack('>iii', 1, 2, 3)

print(var)
print(littleVar)
print(BigVar)

Result

생각한 결과대로 나온것을 확인할 수 있습니다. 그리고 default 값으로는 리틀엔디언이네요.

b'\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00'
b'\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00'
b'\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x03'

\x01\x00\x00\x00 -> 1

\x02\x00\x00\x00 -> 2

\x03\x00\x00\x00 -> 3

UnPack

import struct
 
var = struct.pack('iii', 1, 2, 3)
unpackvar = struct.unpack('iii', var)
print(unpackvar)
print(type(unpackvar))
 
print(struct.calcsize('iii'))

Result

(1, 2, 3)
<class 'tuple'>
12

Collection

앞전에 struct 모듈을 이용했습니다. 요번에는 collection 모듈에 있는 namedtuple 이용해볼게요

https://docs.python.org/3/library/collections.html#collections.namedtuple 사이트에 나와있는 글을 보겠습니다.

240/5000 namedtuplestuple의 각 위치에 의미를 부여하고 읽기 쉬운 자체 문서화 코드를 허용합니다. 정규 tuple이 사용되는 모든 곳에서 사용할 수 있으며 위치 색인 대신 이름으로 필드에 액세스하는 기능을 추가했다고 합니다.

간단한 예제로 사용해볼게요.

Examples

import collections
 
Person = collections.namedtuple('Person', 'name age job')
print(type(Person))
 
p1 = Person(name='Chul-Soo', age=29, job='Doctor')
print(p1)
 
p2 = Person('Young-Hee', 18 , 'Student')
print(p2.name)
 
for i in [p1, p2]:
    print('Name is : %s, Age is : %d, Job is : %s' % i)

Result

<class 'type'>
Person(name='Chul-Soo', age=29, job='Doctor')
Young-Hee
Name is : Chul-Soo, Age is : 29, Job is : Doctor
Name is : Young-Hee, Age is : 18, Job is : Student

namedtuple docs에서 지원하는 예제를 가지고 사용해보겠습니다. 오역, 의역이 있을 수 있으니 참고해주시기 바랍니다…..

classmethod somenamedtuple._make(iterable)

sequence 또는 iterable한 객체를 이용하여 새로운 인스턴스를 만들어 줍니다.

>>> t = [11, 22]
>>> Point._make(t)
Point(x=11, y=22)

somenamedtuple._asdict()

필드의 이름과 값을 이용하여 dict 형태로 반환해 줍니다.

>>> p = Point(x=11, y=22)
>>> p._asdict()
{'x': 11, 'y': 22}

somenamedtuple._replace(**kwargs)

namedtuple 에 특정한 필드와 값에 새로운 값을 대입하여 새로운 인스턴스를 만들어 줍니다.

>>> p = Point(x=11, y=22)
>>> p._replace(x=33)
Point(x=33, y=22)

>>> for partnum, record in inventory.items():
...     inventory[partnum] = record._replace(price=newprices[partnum], timestamp=time.now())

somenamedtuple._fields

기존에 존재하는 namedtuple에 필드들을 이용하여 새로운 namedtuple 을 만들어 줍니다.

>>> p._fields            # view the field names
('x', 'y')

>>> Color = namedtuple('Color', 'red green blue')
>>> Pixel = namedtuple('Pixel', Point._fields + Color._fields)
>>> Pixel(11, 22, 128, 255, 0)
Pixel(x=11, y=22, red=128, green=255, blue=0)

Leave a comment