| |
&theme=102)
ประเภทและข้อมูลตัวแปรภายในภาษาไพธอน (ขั้นสูง) เขียนโดย อ.จักรกฤษณ์ แสงแก้ว สาขาสารสนเทศศาสตร์ คณะวิทยาการสารสนเทศ มหาวิทยาลัยมหาสารคาม
บทนี้อธิบายโมดูลต่าง ๆ ที่สามารถนำมาใช้ในการแปลงข้อมูลระหว่างอ็อบเจ็คไพธอนไปเป็นข้อมูลรูปแบบอื่น
ๆ ซึ่งโมดูลเหล่านั้นถูกใช้ในการอ่านและเขียนฟอร์แมตของไฟล์แบบต่าง ๆ หรือเก็บและแปลงข้อมูลที่เป็นตัวแปรของภาษาไพธอน
ข้อมูลไบนารี่
ไพธอนมีโมดูลหลายตัวที่ใช้ช่วยในการเข้าและถอดรหัสข้อมูลไบนารี่ เช่น
- โมดูล struct ใช้สำหรับแปลงระหว่างข้อมูลโครงสร้างไบนารี่ (คล้าย C Struct)
และข้อมูล Tuple ของไพธอน
- โมดูล array ใช้สำหรับห่อหุ้มข้อมูลอาร์เรย์แบบไบนารี่ ( C Arrays) เข้ามาภายในไพธอนเป็นอ็อบเจ็คแบบซีเควนซ์
รูปแบบ
การแปลงข้อมูลระหว่างโปรแกรมไพธอน โดยใช้โมดูล
- marshal ใช้การอธิบายข้อมูลง่าย ๆ ซึ่งสนับสนุน Built-in data types รวมถึงอ็อบเจ็คที่เป็น
code object(compiled) ไพธอนใช้รูปแบบดังกล่าวอธิบายตัวมันเอง ดังนั้นการเก็บไฟล์เอาไว้บนดีกส์จะอยู่ในรูปแบบ
(PyC Files)
- pickle ใช้อธิบายรูปแบบซับซ้อนมากกว่า ซึ่งสนับสนุน User-defined Classes
และการอ้างถึงโครงสร้างข้อมูล และอื่น ๆ ซึ่งโมดูลดังกล่าวนี้อธิบายได้สองเวอร์ชั่น
คือ pickle และ cpickle ซึ่งแบบแรกถูกเขียนด้วยไพธอนและค่อนข้างทำงานได้ช้า
ส่วน cPicle เขียนด้วยภาษา C และทำงานได้เร็วเหมือนกับโมดูล marshal
รูปแบบปลายทาง
โมดูลในกลุ่มนี้เป็นฟังก์ชั่นที่บอกรูปแบบข้อมูลคล้ายคำสั่ง repr และเครื่องหมาย
% เพื่อใช้กับสตริง
- โมดูล pprint สำหรับ print ข้อมูลทุกชนิดของไพธอน ซึ่งอยู่ในรูปแบบที่อ่านได้
- โมดูล repr เป็น built-in function ซึ่งจะสามารถนำไปใช้ได้โดยอักขระต้องไม่มากกว่า
30 ตัวอักษรของแต่ละสตริง
การเข้ารหัสไบนารี่
ไพธอนสนับสนุนการเข้ารหัส เช่น base64, binhex(ของแม็คอินทอช) , quoted
printable, และการเข้ารหัสแบบ uu
โมดูล array
โมดูลนี้มีประสิทธิภาพในการเก็บข้อมูลแบบอาร์เรย์ และคล้ายกับตัวแปรลีสต์
แต่ทุก ๆ ไอเท็มต้องเป็นชนิดข้อมูลเดียวกันเท่านั้น ซึ่งชนิดข้อมูลจะต้องถูกกำหนดเมื่อมีการสร้างอาร์เรย์
|
'c'
|
char
|
character
|
1
|
|
'b'
|
signed char
|
int
|
1
|
|
'B'
|
unsigned char
|
int
|
1
|
|
'u'
|
Py_UNICODE
|
Unicode character
|
2
|
|
'h'
|
signed short
|
int
|
2
|
|
'H'
|
unsigned short
|
int
|
2
|
|
'i'
|
signed int
|
int
|
2
|
|
'I'
|
unsigned int
|
long
|
2
|
|
'l'
|
signed long
|
int
|
4
|
|
'L'
|
unsigned long
|
long
|
4
|
|
'f'
|
float
|
float
|
4
|
|
'd'
|
double
|
float
|
8
|
พิจารณาตัวอย่างต่อไปนี้
|
ตัวอย่าง :
|
>>>
from array import array
>>> a = array("B", [1, 2, 3, 4, 5, 6])
>>> f = array("B", [1.2 , 2,3 , 4,5 , 5.2]) |
ภายในโมดูล array ประกอบด้วย member function ดังต่อไปนี้
array
ArrayType
typecode
itemsize
append( x)
buffer_info( )
byteswap( )
count( x)
extend( a)
fromfile( f, n
fromlist( list)
fromstring( s)
fromunicode( s)
index( x)
insert( i, x)
pop( [i])
read( f, n)
remove( x)
reverse( )
tofile( f)
tolist( )
tostring( )
tounicode( )
write( f)
สรุป : โมดูล array มีประสิทธิภาพในการแปลงข้อมูลดิบที่เป็นไบนารี่ให้อยู่ในรูป
sequence ซึ่งมีชนิดเป็น integer, float และอื่น ๆ
|
ตัวอย่าง :
|
>>>
from array import
array
>>> a = array("i"
, "1234 1234567
123456789abcdef")
>>> b = array("i"
, "1234 1234567 1234567 1234567")
>>> c = array("i"
, "1234 1234567 1234567 1234567
1234567 1234567 1234567 1234567 1234567 1234567 1234567 1234567")
>>> print
a
array('i', [875770417, 858927392, 926299444,
858927392, 926299444, 1650538808, 1717920867])
>>> print
b
array('i', [875770417, 858927392, 926299444,
858927392, 926299444, 858927392, 926299444])
>>> print
a.tolist()
[875770417, 858927392, 926299444, 858927392, 926299444, 1650538808,
1717920867]
>>> print repr(a.tostring())
'1234 1234567 123456789abcdef' |
# อาร์เรย์เป็นแบบเลขจำนวนเต็ม และป้อนเป็นสตริงที่มีขนาด 4 , 7, 16 ไบต์ตามลำดับ
# สตริงชุดแรกต้องมี 4 ไบต์เท่านั้น และชุดที่ตามมาจะเป็น 7 หรือ 16 ก็ได้
โมดูล struct
โมดูล struct ประกอบด้วยฟังก์ชั่นต่าง ๆ สำหรับแปลงระหว่างสตริงแบบไบนารีและชนิด
tuple
| x |
pad byte |
no value |
|
| c |
char |
string of length 1 |
|
| b |
signed char |
integer |
|
| B |
unsigned char |
integer |
|
| h |
short |
integer |
|
| H |
unsigned short |
integer |
|
| i |
int |
integer |
|
| I |
unsigned int |
long |
|
| l |
long |
integer |
|
| L |
unsigned long |
long |
|
| q |
long long |
long |
(1) |
| Q |
unsigned long long |
long |
(1) |
| f |
float |
float |
|
| d |
double |
float |
|
| s |
char[] |
string |
|
| p |
char[] |
string |
|
| P |
void * |
integer |
|
| @ |
native |
native |
| = |
native |
standard |
| < |
little-endian |
standard |
| > |
big-endian |
standard |
| ! |
network (= big-endian) |
standard |
|
ตัวอย่าง :
|
>>>
from struct import
*
>>> m = pack('ii', 99,33)
>>> m
'c\x00\x00\x00!\x00\x00\x00'
>>> unpack('ii',m)
(99, 33)
>>> calcsize('ii')
8 |
ตัวอย่างนี้เมื่อเรียกใช้ฟังก์ชั่น pack โดยกำหนดให้มีสมาชิกสองตัว คือ 99
และ 33 โดยให้ทั้งสองเป็นชนิดเลขจำนวนเต็ม (integer) จึงใส่ "ii"
ซึ่งหมายถึง integer สองตัว เมื่อผ่านเข้าไปในฟังก์ชั่น pack() จะได้ผลลัพธ์เป็นสตริง
และถ้าเอาสตริงดังกล่าวมาผ่านฟังก์ชั่น unpack() โดยกำหนดให้มีชนิดเป็น integer
ทั้งสองตัว ("ii") และป้อนสตริงที่เก็บในตัวแปร m เข้าไปในฟังก์ชั่น
unpack() จะได้ผลลัพธ์เป็นอาร์เรย์ ซึ่งมีค่า (99,33) และนำไปใช้ในไพธอนได้โดยไม่ต้องไปแปลงชนิดข้อมูล
ในขณะที่ฟังก์ชั่น calsize() ใช้สำหรับคำนวณหาขนาดไบต์ทั้งหมดที่ต้องใช้ไป
โดยในตัวอย่างนี้ integer ใช้พื้นที่ 4 ไบต์ และ "ii" หมายถึง
integer สองตัวจึงมีขนาดเท่ากับ 8 ไบต์
โมดูล xdrlib
โมดูล xdrlib สำหรับแปลงข้อมูลระหว่างตัวแปรในไพธอนและบริษัท XDR (บริษัท
Sun)
รูปแบบ XDR ใช้สำหรับ Remote Procedure Call ของบริษัท Sun
|
>>> import
xdrlib
>>> m = xdrlib.Packer()
>>> m.pack_uint(555)
>>> m.pack_string("Hello
World")
>>> data = m.get_buffer()
>>> print
repr(data)
'\x00\x00\x02+\x00\x00\x00\x0bHello World\x00'
>>> m = xdrlib.Unpacker(data)
>>> m.unpack_uint()
555
>>> m.unpack_string()
"Hello World"
>>> m.done()
|
ในตัวอย่างนี้เป็นการแปลงข้อมูลในรูปแบบข้อมูลเหมือนในตัวอย่างที่ผ่านมา
โดยให้ m เป็นอ็อบเจ็คของคลาส Packer()
จากนั้นเริ่มแพ็คตัวเลข 555 ลงไป และแพ็ก "Hello World" ลงไป จากนั้นตัวแปร
data จะเก็บข้อมูลที่ได้รับการเข้ารหัส (pack) เรียบร้อยแล้วซึ่งอยู่ในรูปสตริงทั่วไป
ลำดับถัดมาสร้างอ็อบเจ็ค m เป็นคลาสของ Unpacker() และเรียกใช้ฟังก์ชั่น
unpack_uint() และ unpack_string() ตามลำดับ ต้องไม่ทำสลับกันเพราะลำดับการแพ็คต้องสอดคล้องกับลำดับการ
unpack เมื่อเสร็จเรียบร้อยให้เรียกฟังก์ชั่น done() เพื่อจบทำลายอ็อบเจ็ค
m และเคลียส์ค่าของบัฟเฟอร์อ็อบเจ็ค m
โมดูล marshal
โมดูล marshal ใช้สำหรับแปลงข้อมูลระหว่าง character strings เพื่อให้สามารถเก็บลงบนไฟล์หรือส่งไปยังเน็ตเวอร์คได้
|
>>> from
marshal import *
>>> m = ("Hello
World",[1,2,3,4])
>>> data = dumps(m)
>>> k = loads(data)
>>> print
k
('Hello World', [1, 2, 3, 4])
|
ตัวอย่างนี้เป็นการแปลงข้อมูลซึ่งเป็นตัวแปรของไพธอนให้เป็นสตริงด้วยฟังก์ชั่น
dump() จากนั้นแปลงสตริงดังกล่าวกลับมาด้วยฟังก์ชั่น load() จะทำให้สามารถแปลงชนิดตัวแปรไพธอนไปมาได้อย่างสะดวกและสามารถบันทึกลงไฟล์ได้ด้วย
(เพราะเป็นชนิดสตริง)
|
>>> from
marshal import *
>>> t =
'print "Hello World"'
>>> bytecode = compile(t,'','exec')
>>> m = dumps(bytecode)
>>> f = open("c:\\temp\\m.pyc","wb").write(m)
>>> exec
loads(open("c:\\temp\\m.pyc","r").read())
Hello World
|
ตัวอย่างด้านบนนี้นับว่ามีประโยชน์อย่างมาก เพราะในขั้นแรกเราได้ทำการเขียนคำสั่งภาษาไพธอนเก็บไว้ในตัวแปร
t จากนั้นคอมไพล์และได้ผลเป็น bytecode ในลำดับถัดมานำเอา bytecode (ซึ่งมีชนิดเป็น
code ในไพธอน) และเก็บไว้ในตัวแปร m โดยผ่านการ dumps() ให้เป็นสตริง นำเอาสตริงเก็บไว้ในไฟล์
และเปิดไฟล์ดังกล่าวขึ้นมาเอ็กซีคิวส์
โมดูล pickle
โมดูล pickle ทำงานเหมือน marshal แต่ไม่สามารถเก็บอ็อบเจ็คชนิด code ได้เหมือน
marshal แต่สามารถเก็บข้อมูลที่เป็นชนิดคลาสและอินสแตนท์ได้ การประมวลผลจึงช้ากว่า
โมดูล marshal ถ้าต้องการให้เก็บข้อมูลชนิด code object ต้องใช้โมดูล copy_reg
ร่วมด้วย
โมดูล cPickle
โมดูล cPickle เป็นการปรับปรุงโมดูล pickle ให้เร็วขึ้น ซึ่งโมดูล cPickle
เขียนขึ้นด้วยภาษาซี
โมดูล pprint
โมดูล pprint สำหรับการพิมพ์ผ่านเครื่องพิมพ์ เป็นประโยชน์ถ้าท่านต้องพรินต์ข้อมูลที่เป็นโครงสร้างข้อมูลลงไปยังคอนโซล
โมดูล base64
โมดูล base64 ใช้สำหรับแปลงข้อมูลไบนารีสตริงให้เป็นเท็กซ์ธรรมดา มีสองฟังก์ชั่นสำคัญ
encode() และ decode()
>>> from
base64 import *
>>> encode(open("c:\\temp\\a.txt"),open("c:\\temp\\b.txt",'w'))
C:\temp>type a.txt
Hello world
C:\temp>type b.txt
SGVsbG8gd29ybGQK
|
โมดูล repr
ใช้สำหรับแสดงเครื่องหมาย string ให้กับสตริงที่เป็นแบบ recusive (เกิดซ้ำ)
โมดูล binhex
โมดูล binhex สำหรับแปลงข้อมูลไบนารีสตริงเป็น Macintosh binhex
|
>>> from
binhex import binhex
>>> binhex('c:\\temp\\a.txt','c:\\temp\\b.txt')
C:\temp>type a.txt
Hello world
C:\temp>type b.txt
(This file must be converted with BinHex 4.0)
:"@%ZG(Kd!&4&@&3rN!3!N!80!*!%3@T)C@aXEb"hEh*XC!d+RVX!!!:
|
โมดูล quopri
โมดูล quopri สำหรับเข้ารหัส ขึ้นอยู่กับมาตรฐานของ MIME ซึ่งใช้เข้ารหัสและสามารถนำไปใช้ได้
ถ้าท่านต้องการเปีล่ยนข้อความซึ่งประกอบด้วย US ASCII Text เช่น ข้อความที่เขียนขึ้นจากภาษายุโรปไปเป็นข้อความที่ใช้เพียง
US ASCII โมดูลนี้มีประโยชน์ถ้าท่านส่งผ่าน steam-powered mail transports
ไปให้ผู้ที่ใช้ vintage mail agents
|
>>> from
quopri import encode
>>> encode(open("c:\\temp\\a.txt"),open("c:\\temp\\b.txt",'w'),0)
C:\temp>type a.txt
Hello world
C:\temp>type b.txt
Hello world
|
โมดูล uu
โมดูล uu ใช้เข้ารหัสและแปลงเป็นข้อมูลไบนารีไปเป็นเท็กซ์ธรรมดา นิยมนำไปใช้ใน
usenet แต่ว่าจะช้าเพราะมีแม่เป็น base64 encoding
การเข้ารหัส UU ใช้ 24 บิต และแปลงแต่ละกลุ่มเป็นลำดับทีละ 4 ตัวอักษร(6
บิตต่อตัวอักษร) การใช้อักขระจาก chr(32) ซึ่งเป็นสเปสบาร์ ไปเป็น chr(95)
รวมถึงความยาวและอักขระขึ้นบรรทัดใหม่ ซึ่งการเข้ารหัสแบบ UU ปกติแล้วขยายข้อมูลขึ้นไปได้
40%
|
>>> from
quopri import encode
>>> encode(open("c:\\temp\\a.txt"),open("c:\\temp\\b.txt",'w'))
C:\temp>type a.txt
Hello world
C:\temp>type b.txt
begin 666 a.txt
-2&5L;&\@=V]R;&0-"@
end
|
โมดูล binascii
โมดูล binascii สำหรับเข้ารหัส รวมถึง base64, binhex และ uu ซึ่งเวอร์ชั่นใหม่นี้อนุญาตให้ท่านแปลงข้อมูลไบนารีจากรูปแบบ
hexadecimal strings ได้
|
>>> from
binascii import b2a_base64,
a2b_base64
>>> from
binascii import b2a_uu, a2b_uu
>>> from
binascii import b2a_hex,
a2b_hex
>>>
text = "Hello"
>>> m
= b2a_base64(text)
>>> n
= a2b_base64(m)
>>> print
m,n
SGVsbG8=
Hello
>>> m
= b2a_uu(text)
>>> n
= a2b_uu(m)
>>> print
m,n
%2&5L;&\
Hello
>>> m
= b2a_hex(text)
>>> n
= a2b_hex(m)
>>> print
m,n
48656c6c6f Hello
|
|
|
|