Tuples (ทูเพิล)#

ในบทนี้ คุณจะได้เรียนรู้เกี่ยวกับ Tuple ในภาษาไพธอน และทำความรู้จักกับ Tuple ว่าคืออะไร เรียนรู้วิธีการประกาศและการใช้งาน Tuple นอกจากนี้ ยังจะอธิบายถึงการใช้งานเมธอดและฟังก์ชันต่างๆ ของ Tuple

Ref:


ชุดข้อมูล (Dataset)#

\(\qquad\) Dataset หรือที่เรียกว่า “ชุดข้อมูล/เซ็ทของข้อมูล” หมายถึง ข้อมูลที่ถูกจัดให้เป็นกลุ่มถูกต้องตามลักษณะโครงสร้างข้อมูล สามารถที่จะนำไปใช้ประมวลผลได้ บางครั้งใช้ในความหมายเหมือน “แฟ้มข้อมูล”

\(\qquad\) สมมุติว่าคุณได้รับชุดข้อมูล (Dataset) เพลงซึ่งเป็นข้อมูลของเพลงฮิตในแต่ละปี (2010~2019) ในรูปแบบของตาราง โดยแต่ละแถว (row) ในตารางเป็นข้อมูลของเพลงแต่ละเพลง และแต่ละคอลัมน์ (column) มีข้อมูลดังต่อไปนี้

  • artist - ชื่อศิลปิน (นักร้อง วงดนตรี)

  • genre คือแนวเพลงหรือประเภทของแนวดนตรี เช่น pop, pop dance, rock

  • year คือปี (ค.ศ) ของเพลงที่อยู่ในบิลบอร์ด (Billboard)

  • bpm (Beats.Per.Minute: Tempo) คือจังหวะเร็วช้าขนาดไหน หน่วยเป็น bpm

  • nrgy (Energy) คือพลังหรือความพุ่งของเพลง

  • dnce (Danceability) คือความดิ้น หรือความน่าเต้นของเพลง

  • dB (Loudness) คือระดับความดังในหน่วย decibel

  • live (Liveness) คือระดับของการแสดงสด (Live) ของเพลง

  • val (Valence) คือระดับความเป็นเชิงบวก (positive) ในเพลง (ค่าต่ำ: เศร้า-หดหู่-โกรธ,ค่าสูง: มีความสุข-ให้กำลังใจ)

  • dur (Length) - คือความยาว (ระยะเวลา) ของเพลง/ดนตรี

  • acous (Acousticness) คือความ “acoustic” ของเพลง

  • spch (Speechiness) คือปริมาณของคำพูดหรือเนื้อร้อง

  • pop (Popularity) คือระดับความนิยม ยิ่งค่าสูงเท่าไหร่ ยิ่งเป็นที่นิยม



ชุดข้อมูลที่ได้รับอยู่ในรูปตาราง (Format CSV)

(Source: spotifycharts.com, kaggle.com)

#

title

artist

genre

year

bpm

nrgy

dnce

dB

live

val

dur

acous

spch

pop

1

Memories \(\triangleright\)

Maroon 5

pop

2019

91

32

76

-7

8

57

189

84

5

99

2

Lose You To Love Me \(\triangleright\)

Selena Gomez

dance pop

2019

102

34

51

-9

21

9

206

58

4

97

3

Someone You Loved \(\triangleright\)

Lewis Capaldi

pop

2019

110

41

50

-6

11

45

182

75

3

96

4

Senorita \(\triangleright\)

Shawn Mendes

canadian pop

2019

117

54

76

-6

9

75

191

4

3

95

5

How Do You Sleep? \(\triangleright\)

Sam Smith

pop

2019

111

68

48

-5

8

35

202

15

9

93

6

South of the Border (feat. Camila Cabello & Cardi B)

Ed Sheeran

pop

2019

98

62

86

-6

9

67

204

15

8

92

7

Trampoline (with ZAYN)

SHAED

electropop

2019

127

46

62

-6

14

50

184

56

3

92

8

Happier

Marshmello

brostep

2019

100

79

69

-3

17

67

214

19

5

90

9

Truth Hurts

Lizzo

escape room

2019

158

62

72

-3

12

41

173

11

11

90

10

Good as Hell (feat. Ariana Grande) - Remix

Lizzo

escape room

2019

96

89

67

-3

74

48

159

30

6

90

11

Underneath the Tree

Kelly Clarkson

dance pop

2013

160

81

51

-5

21

69

230

0

5

88

12

Higher Love

Kygo

edm

2019

104

68

69

-7

10

40

228

2

3

88

13

Shape of You

Ed Sheeran

pop

2017

96

65

83

-3

9

93

234

58

8

87

14

Only Human

Jonas Brothers

boy band

2019

94

50

80

-6

6

87

183

11

7

87

15

All of Me

John Legend

neo mellow

2014

120

26

42

-7

13

33

270

92

3

86


ออบเจกต์ประเภท Collections และประเภทลำดับ (Sequences)#

โครงสร้างข้อมูลในภาษาไพธอนสามารถแบ่งออกเป็น 2 ประเภทใหญ่ๆ คือ

  • ออบเจกต์ประเภท Collections

  • ออบเจกต์ประเภทลำดับ (Sequences)

\(\qquad\) ออบเจกต์ประเภท Collections (หรือ Container datatype) เป็นออบเจกต์ที่เก็บข้อมูลหลายๆ ข้อมูลรวมกันเป็นชุดข้อมูลเดียวกัน และใช้ชื่อตัวแปรตัวเดียวกัน โดยในภาษาไพธอน มีชนิดของข้อมูลที่เป็นประเภท Collections พื้นฐานอยู่ 4 ชนิด ได้แก่ Tuple, List, Set และ Dictionary

ตัวอย่างของออบเจกต์ประเภท Collections โดยเรียงจาก Tuple, List, Set และ Dictionary ตามลำดับ

coordinates = (1, 9, 5)
languages = ["Python", "C", "C++", "Java", "Perl"]
colors = {'red', 'blue', 'white'}
item_counts = {'computers': 2, 'headphones': 4, 'cellphones': 3}

\(\qquad\) ออบเจกต์ประเภทลำดับ (Sequence หรือ sequential datatype) เป็นออบเจกต์พื้นฐานที่ใช้เก็บชุดข้อมูล (เซ็ทของข้อมูล) ที่มีการจัดเรียงตามลำดับ (Sequence) ในภาษา Python มีออบเจกต์ประเภทลำดับอยู่มากมายหลากหลายชนิด เช่น str, tuple, list และ range ออบเจกต์เหล่านี้สามารถเก็บข้อมูลได้มากกว่าหนึ่งตัวโดยมีการจัดเรียงข้อมูลตามลำดับ และสามารถเข้าถึงข้อมูลภายแต่ละตัวได้โดยใช้เลขดัชนี (index)

ตัวอย่างของออบเจกต์ประเภทลำดับ โดยเรียงจาก str, tuple, list และ range ตามลำดับ

greetings = "Hey, guys!"
coordinates = (1, 9, 5)
languages = ["Python", "C", "C++", "Java", "Perl"]
range(0,10)

Tuples (ทูเพิล) คือ?#

\(\qquad\) ชนิดของข้อมูลในภาษา Python ที่เราได้เรียนรู้ที่ผ่านมา ไม่ว่าจะเป็น float ใช้สำหรับจำนวนจริง, int ใช้สำหรับจำนวนเต็ม, str ใช้สำหรับสตริงหรือข้อความ และ bool ใช้สำหรับข้อมูลแบบตรรกะ (True, False) ข้อมูลที่มีชนิดต่างๆ กันเหล่านี้สามารถทำให้อยู่ในรูปของชุดข้อมูล หรือเซ็ทของข้อมูล (Dataset) เดียวกันที่เรียกว่า “Tuple” (ออกเสียงว่า “ทูเพิล”) ได้

\(\qquad\) Tuple เป็นหนึ่งในออบเจกต์ประเภท Collections และยังเป็นออบเจกต์ประเภทลำดับ (Sequential datatype) อีกด้วย กล่าวคือ มันสามารถเก็บข้อมูลได้หลายชนิดหลายค่าในตัวแปรตัวเดียว (ดังแสดงในรูปด้านล่าง)โดยมีการจัดเรียงลำดับของข้อมูล (เรียงลำดับดังแสดงในรูป) แต่จะไม่สามารถเปลี่ยนแปลง (แก้ไข ลบหรือเพิ่ม) หลังจากที่ถูกสร้างขึ้นมาแล้ว (Tuple เป็นข้อมูลชนิด Immutable เช่นเดียวกับสตริง) และข้อมูลที่เก็บยังสามารถเป็นข้อมูลที่มีชนิดแตกต่างกันได้อีกด้วย (Heterogeneous data) (Tuple ในรูปเก็บข้อมูลชนิด str int และ float)

การสร้าง Tuple#

\(\qquad\) ข้อมูลแบบ Tuple จะถูกเขียนอยู่ในเครื่องหมายวงเล็บ ( )

เราลองมาสร้างตัวแปรชนิด Tuple ที่มีชุดข้อมูลที่ประกอบไปด้วย สตริง (str), จำนวนเต็ม (int) และ จำนวนจริง (float) และใช้งาน Tuple ในเบื้องต้นกัน!

Note

เครื่องหมายวงเล็บในภาษาไพธอน (มีกี่แบบและใช้ต่างกันอย่างไร?)

  • เครื่องหมายวงเล็บสี่เหลี่ยม (สแควร์แบร็กเกต; Square bracket)) [] ใช้สร้าง Lists ใช้กับเลขดัชนี (indexing) ใช้ค้นหา key ในข้อมูลชนิด Dic และใช้ในการตัด (slicing) หรือใช้เป็นโอเปอร์เรเตอร์ในคลาส เช่น

สร้าง Lists: [], [1, 2, 3], [i**2 for i in range(5)]

เลขดัชนี: ‘abc’[0] \(\Rightarrow\) ‘a’

ค้นหา key: {0: 10}[0] \(\Rightarrow\) 10

การตัด: ‘abc’[:2] \(\Rightarrow\) ‘ab’

  • เครื่องหมายวงเล็บ (ราวด์แบร็กเกต; Round brackets, Parentheses) ‘()’ ใช้สร้าง Tuples ใช้จัดลำดับการประมวลผล ใช้เรียกฟังก์ชันหรือเมธอด หรือใช้เป็นโอเปอร์เรเตอร์ในคลาส เป็นต้น เช่น

สร้าง Tuples: (), (1, 2, 3)

จัดลำดับการประมวลผล: (5-1)**2

เรียกฟังก์ชันหรือเมธอด:: print(), int(), range(5), ‘1 2 3’.split(’ ‘)

  • เครื่องหมายวงเล็บปีกา (เคิร์ลลี่แบร็กเกต; curly brackets) {} ใช้สร้าง Dictionaries และ Sets ใช้จัดรูปแบบของสตริง (เมธอด str.format( ) และการเขียนในรูปแบบ f-string)

สร้าง Dicts: {}, {0: 10}, {i: i**2 for i in range(5)}

สร้าง Sets: {0}, {i**2 for i in range(5)}

ยกเว้น set ว่าง (ไม่มีสมาชิก; empty set): set() จัดรูปแบบของสตริงเพื่อแทนที่ รูปแบบ f-strings: f’{total_hour}’ เมธอด format(): ‘{x}’.format(x=total_min)

  • เครื่องหมายวงเล็บมุม (แองเกิลแบร็กเกต; Angle brackets, chevron) ‘<>’ ใช้ในการแสดงชนิดของออบเจ็กต์ เช่น ฟังก์ชัน คลาส และอินสแตนซ์ของคลาส เช่น

<built-in function print>

<class ‘zip’>

<zip at 0x7fddcdf0be80>

# สร้างตัวแปรชนิด Tuple โดยสมาชิกใน tuple ไม่จำเป็นต้องเป็นชนิดเดียวกัน
tuple1 = ("dance",10,1.2 )
tuple1
('dance', 10, 1.2)

เราสามารถใชัฟังก์ชัน type()ตรวจสอบชนิดของตัวแปร tuple1 ได้ ซึ่งแน่นอน มันคือ tuple

# ชนิดของตัวแปร tuple1 ที่สร้างขึ้น
type(tuple1)
tuple

ในกรณีที่สมาชิกมีแค่ตัวเดียว จะไม่เขียนแบบนี้ t1 = ("dance") เพราะจะกลายเป็นข้อมูลชนิด str

t1 = ("dance")
type(t1)
str

แต่ต้องเขียนคั่นด้วยเครื่องหมายจุลภาคแบบนี้แทน (แม้สมาชิกจะมีแค่ตัวเดียว ก็ต้องมีเครื่องหมายจุลภาค!)

t1 = ("dance",)
type(t1)
tuple

อย่างไรก็ตาม การสร้างตัวแปร tuple สามารถที่จะละเว้นวงเล็บได้ แต่ยังคงต้องคั่นแต่ละค่าด้วยเครื่องหมายจุลภาค โดยไพธอนจะแพ็คค่าที่ถูกคั่นด้วยเครื่องหมายจุลภาคที่อยู่ทางขวามือของเครื่องหมาย = รวมไว้เป็น tuple โดยอัตโนมัติ

tuple1 = "dance",10,1.2 
tuple1
('dance', 10, 1.2)
t1 = "dance",
t1
('dance',)

Attention

ขอแนะนำว่า อย่าเพิ่งละวงเล็บในช่วงเริ่มต้นเขียนโปรแกรมไพธอน เพราะจะทำให้งง

ในการกำหนดค่าให้กับตัวแปร tuple เราสามารถกำหนดค่าจากตัวแปรที่มีอยู่ก็ได้ โดยใช้เครื่องหมายวงเล็บ ()

x1 = 1 # กำหนดค่าให้ตัวแปร x1
y1 = 2 # กำหนดค่าให้ตัวแปร y1
z1 = 3 # กำหนดค่าให้ตัวแปร z1
p1 = (x1, y1 ,z1) # กำหนดค่าให้ตัวแปร p1 (ซึ่งเป็น tuple) ที่ประกอบด้วยสมาชิก 1, 2 และ 3
p1 # แสดง p1
(1, 2, 3)

หรือจะละ () แบบนี้ก็ได้ เช่นกัน

p1 = x1, y1 ,z1 # p1 เป็น tuple ที่ประกอบด้วยสมาชิก 1, 2 และ 3
p1
(1, 2, 3)

เราเรียกการกำหนดค่าของสมาชิกหลายๆ ตัวลงในตัวแปร Tuple ตัวเดียวแบบนี้ ว่า “การแพ็คทูเพิล” (Tuple packing; “แพ็ก” ข้อมูลหลายๆ ตัวให้เป็น Tuple)

ในทางกลับกัน ไพธอนก็มี “การอันแพ็คทูเพิล” (Tuple unpacking) ซึ่งเป็นการกระจายหรือการแตกข้อมูลใน Tuple ลงในตัวแปรหลายตัวหลายๆ ตัวพร้อม ๆ กัน

p2 = (6,7,8) # สร้างทูเพิล p2 ที่ประกอบด้วย 3 สมาชิก
x2, y2, z2 = p2 # แตกสมาชิกของ p2 เพื่อกำหนดค่าลงในตัวแปร 3 ตัว x2, y2 และ z2 ตามลำดับ
print("(x2,y2,z2) is ({},{},{})".format(x2, y2, z2)) # แสดงค่าของตัวแปร x2, y2 และ z2 ตามลำดับ
(x2,y2,z2) is (6,7,8)
\[\]

เช่นเดียวกับข้อมูลชนิดสตริง เราสามารถเข้าถึงสมาชิกที่อยู่ใน Tuple ได้โดยใช้ชื่อตัวแปรตามด้วยเลขดัชนีในวงเล็บสี่เหลี่ยม [ ]

tuple1[0]
'dance'

สิ่งที่เหมือนกับข้อมูลชนิดสตริงอีกอย่างคือ เราก็ไม่สามารถเปลี่ยนแปลงหรือแก้ไขสมาชิกของ Tuple ได้

tuple1[0] = 'rock'
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In [11], line 1
----> 1 tuple1[0] = 'rock'

TypeError: 'tuple' object does not support item assignment

ไพธอนจะแจ้งเตือน (TypeError) เนื่องจาก Tuple เป็นประเภทข้อมูลที่ไม่สามารถเปลี่ยนแปลงได้ (Immutable data structure) เช่นเดียวกับข้อมูลชนิดสตริง (Immutable objects: int, float, string, tuple, frozen Set)

แต่ไม่ได้หมายความว่าเราจะเปลี่ยนค่าของตัวแปรให้เป็น tuple อื่นไม่ได้

tuple1 # ค่าของตัวแปร tuple1
('dance', 10, 1.2)
tuple1 = "rock",10,1.2 # เปลี่บนค่าของตัวแปร tuple1 ให้เป็น tuple ใหม่
tuple1
('rock', 10, 1.2)

สรุป: เราไม่สามารถเปลี่ยนแปลงสมาชิกของ tuple ได้ (เนื่องจากเป็นข้อมูล Immutable) แต่เราสามารถเปลี่ยนค่าของตัวแปรให้เป็น tuple อื่นได้

เลขดัชนี (Index)#

\(\qquad\) ตารางต่อไปนี้แสดงความสัมพันธ์ระหว่างเลขดัชนีและสมาชิกที่อยู่ภายใน Tuple

เราสามารถเข้าถึงสมาชิกที่อยู่ใน Tuple ได้ โดยใช้ชื่อตัวแปรตามด้วยวงเล็บเหลี่ยม [ ] ที่มีเลขดัชนี

Tip

ในภาษาไพธอน เลขดัชนี (Index) จะเริ่มจาก “0” เสมอ

เราสามารถใช้ฟังก์ชัน print( ) แสดงสมาชิกแต่ละตัวที่อยู้ใน Tuple ได้

# แสดงค่าของสมาชิกแต่ละตัวที่อยู่ในตัวแปรออกหน้าจอโดยใช้เลขดัชนี

print(tuple1[0])
print(tuple1[1])
print(tuple1[2])
rock
10
1.2

เราสามารถใชัฟังก์ชัน type( ) ตรวจสอบสมาชิกแต่ละตัวของ Tuple ว่าเป็นข้อมูลชนิดใด

# แสดงชนิดข้อมูลของสมาชิกแต่ละตัวที่อยู่ในตัวแปรออกหน้าจอโดยใช้เลขดัชนี

print(type(tuple1[0]))
print(type(tuple1[1]))
print(type(tuple1[2]))
<class 'str'>
<class 'int'>
<class 'float'>

ถ้าเรารู้ว่าใน Tuple มีสมาชิกที่มีมีค่า 10 อยู่ เราสามารถหาตำแหน่ง (เลขดัชนี) ของ 10 ได้โดยใช้เมธอด index()

เมธอด index() จะส่งกลับเป็นเลขดัชนีของสมาชิกที่อยู่ใน Tuple

Note

เมธอด index() ยังสามารถใช้กับออบเจ็กต์ประเภทลำดับ (Sequence) อื่นๆ เช่น str, tuple, list, range เป็นต้น ก็ได้

tuple1.index(10)
1

นอกจากนี้ เรายังสามารถใช้ดัชนีเชิงลบ (Negative index) กับ Tuple ได้เช่นกัน

Tip

ดัชนีของข้อมูลตัวสุดท้ายมีค่าเป็น -1 ! (เช่นเดียวกับสตริง)

# ดัชนีเชิงลบมักใช้ในการเข้าถึงสมาชิกตัวสุดท้าย

tuple1[-1]
1.2

ข้อมูลตัวถัดไป และตัวถัดๆ ไป

# ใช้ดัชนีเชิงลบเข้าถึงสมาชิกตัวรองสุดท้าย

tuple1[-2]
10
# ใช้ดัชนีเชิงลบเข้าถึงสมาชิกตัวตัวที่สามจากท้าย

tuple1[-3]
'rock'

การเชื่อม Tuple (Concatenate Tuples)#

\(\qquad\) เราสามารถเชื่อมหรือรวม Tuple เข้าด้วยกันโดยใช้โอเปอร์เรเตอร์ '+' และผลลัพธ์ที่ได้คือ Tuple ใหม่ที่รวมสมาชิกของทั้งสองเข้าด้วยกัน

# เชื่อม 2 Tuple เข้าด้วยกัน

tuple2 = tuple1 + ("dance pop", 10)
tuple2
('rock', 10, 1.2, 'dance pop', 10)

การตัด (Slicing) Tuple#

\(\qquad\) เราสามารถตัด (Slicing) Tuple ได้หลายค่า ดังแสดงในรูปด้านล่าง

# ตัดสมาชิกตั้งแต่ดัชนี 0 ถึงดัชนี 2

tuple2[0:3]
('rock', 10, 1.2)

# ตัดสมาชิกตั้งแต่ดัชนี 3 ถึงดัชนี 4

tuple2[3:5]
('dance pop', 10)

เราสามารถหาจำนวนสมาชิกทั้งหมดที่อยู่ใน Tuple ได้โดยใช้ฟังก์ชัน len() ซึ่งย่อมาจาก length

# จำนวนสมาชิกทที่อยู่ใน Tuple

len(tuple2)
5

การจัดเรียงข้อมูล (Sorting)#

\(\qquad\) ตัวแปร Ratings ด้านล่างนี้เป็นข้อมูลชนิด Tuple ที่มีสมาชิกเป็นเลขจำนวนเต็ม (int)

# กำหนดตัวแปร Tuple เก็บค่าเรตติ้ง

Ratings = (0, 9, 6, 5, 10, 8, 9, 6, 2)

เราสามารถจัดเรียงข้อมูลที่อยู่ใน Tuple และบันทึกค่าเป็น Tuple ใหม่ได้

# จัดเรียง tuple ด้วยฟังก์ชัน sorted

RatingsSorted = sorted(Ratings)
RatingsSorted
[0, 2, 5, 6, 6, 8, 9, 9, 10]

ฟังก์ชัง sorted() ส่งกลับเป็นข้อมูลชนิด List ลองตรวจสอบชนิดของข้อมูลด้วยฟังก์ชัน type()

type(RatingsSorted)
list

เราสามารถเปลี่ยนชนิดข้อมูลจาก list ให้เป็น tuple ได้โดยใช้ฟังก์ชัน tuple()

tuple(RatingsSorted)
(0, 2, 5, 6, 6, 8, 9, 9, 10)

Tuple ที่สมาชิกมีชนิดข้อมูลต่างชนิดกัน จะไม่สามารถเรียกฟังก์ชัน sorted() ได้ ดังตัวอย่างต่อไปนี้

mixed_numbers = (5, "1", 100, "34")
sorted(mixed_numbers)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In [28], line 2
      1 mixed_numbers = (5, "1", 100, "34")
----> 2 sorted(mixed_numbers)

TypeError: '<' not supported between instances of 'str' and 'int'

ไพธอนแจ้งเตือนเป็น ‘TypeError’ เนื่องจากมีสมาชิกบางตัวเป็นสตริง บางตัวเป็นตัวเลข ไม่เป็นชนิดเดียวกันทั้งหมด ในกรณีเราต้องทำการเปลี่ยนชนิดของข้อมูลก่อน โดยใช้ฟังก์ชันที่ชื่อเดียวกับชนิดข้อมูล แล้วจึงเรียกใช้ฟังก์ชัน sorted() จัดเรียงข้อมูล

# เปลี่ยนสมาชิกทุกตัวจากชนิิด str ให้เป็นชนิด int
 
sorted_numbers = (int(mixed_numbers[0]),)+(int(mixed_numbers[1]),)+(int(mixed_numbers[2]),)+(int(mixed_numbers[3]),)
sorted_numbers
(5, 1, 100, 34)

หรือ อาจะเขียนโค้ดให้สั้นๆ ได้โดยใช้ comprehension

# ใช้ Tuple comprehension แปลงค่าทั้งหมดให้เป็นจำนวนเต็ม
sorted((int(x) for x in mixed_numbers))
[1, 5, 34, 100]

หากต้องการให้เรียงจากมากไปหาน้อย ก็สามารถทำได้โดยส่งอาร์กิวเมนต์ reverse=True

# เรียงจากมากไปหาน้อย reverse=True 
sorted((int(x) for x in mixed_numbers), reverse=True)
[100, 34, 5, 1]

สรุป: sorted() เป็นฟังก์ชัฝังตัว (Built-in function) เหมือนฟังก์ชัน print() ใช้จัดเรียงข้อมูล ใช้ได้กับข้อมูลที่เป็นตัวเลขและสตริง แต่ชนิดข้อมูลที่จัดเรียงต้องเป็นชนิดใดชนิดหนึ่งเหมือนกันทั้งหมด ผสมปนรวมกันไม่ได้! โดยจะจัดเรียงจากน้อยไปหามาก (reverse=False เป็นค่าดีฟอลต์) และส่งกลับเป็นข้อมูลชนิด List ที่จัดเรียงเรียบร้อยแล้ว (หากต้องการเปลี่ยน List ให้เป็น Tuple ก็สามารถทำได้ใช้ฟังก์ชัน tuple())

Note

  • ฟังก์ชัน tuple() ใช้เปลี่ยนข้อมูล (เช่น เปลี่ยน List) ให้เป็น Tuple

  • ฟังก์ชัน list() ใช้เปลี่ยนข้อมูล (เช่น เปลี่ยน Tuple) ให้เป็น List

นอกจากฟังก์ชัน sorted() แล้ว ยังมีฟังก์ชัน max() และ min()

tup = (-70, -80, 10, 20, 30, 0, 29, -97)
biggest = max(tup)
smallest = min(tup)
print('The biggest numner:', biggest)
print('The smallest numner:', smallest)
The biggest numner: 30
The smallest numner: -97

เช่นเดียวกับฟังก์ชัน sorted() ฟังก์ชัน max() และ min() ยังใช้กับข้อมูลชนิดสตริงก็ได้

min('กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรลวศษสหฬอฮ')
'ก'
max('๐๑๒๓๔๕๖๗๘๙')
'๙'

Tuple ซ้อน Tuple (Nested Tuple)#

\(\qquad\) สมาชิกที่อยู่ใน Tuple สามารถเป็น Tuple หรือข้อมูลที่ซับซ้อนอื่นๆ ก็ได้ เราเรียกระบวนการนี้ว่า ‘การซ้อน (nesting)’

ลองพิจารณา Tuple ที่มีสมาชิกหลากหลายชนิด (มีสมาชิกที่เป็น int, Tuple และ Nested Tuple) ต่อไปนี้

# สร้าง nested tuple

NestedT =(1, 2, ("pop", "rock") ,(3,4),("dance",(1,2)))
NestedT
(1, 2, ('pop', 'rock'), (3, 4), ('dance', (1, 2)))

เราสามารถเข้าถึงสมาชิกแต่ละตัวที่อยู่ใน Tuple (“Tuple หลัก”) รวมถึงสมาชิกที่เป็น Tuple (“Tuple สมาชิก”) ได้โดยใช้เลขดัชนี (Index) ดังแสดงในรูป

# แสดงสมาชิกแต่ละดัชนี

print("Element 0 of Tuple: ", NestedT[0])
print("Element 1 of Tuple: ", NestedT[1])
print("Element 2 of Tuple: ", NestedT[2])
print("Element 3 of Tuple: ", NestedT[3])
print("Element 4 of Tuple: ", NestedT[4])
Element 0 of Tuple:  1
Element 1 of Tuple:  2
Element 2 of Tuple:  ('pop', 'rock')
Element 3 of Tuple:  (3, 4)
Element 4 of Tuple:  ('dance', (1, 2))

เราเรียก NestedT ว่า “Tuple หลัก” และเรียก ('pop', 'rock'), (3, 4) และ ('dance', (1, 2)) ว่า “Tuple สมาชิก”

เราสามารถใช้เลขดัชนี (Index) ตัวที่สองต่อท้ายดัชนีตัวแรก เพิ่อเข้าถึงสมาชิกที่อยู่ใน Tuple สมาชิกได้ ดังรูป

(ทั้งนี้ เลขดัชนี ไม่ว่าจะเป็นตัวแรกหรือตัวที่สอง … จะต้องอยู่ในเครื่องหมายวงเล็บสี่เหลี่ยม [] เสมอ)

ลองเข้าถึงข้อมูล Tuple ซ้อน Tuple กัน

ก่อนอื่น เข้าถึงสมาชิกแต่ละสมาชิกที่อยู่ใน Tuple สมาชิก (รูปข้างต้น)

# แสดงแต่ละสมาชิกที่อยู่ใน Tuple สมาชิก

print("Element 2, 0 of Tuple: ",   NestedT[2][0])
print("Element 2, 1 of Tuple: ",   NestedT[2][1])
print("Element 3, 0 of Tuple: ",   NestedT[3][0])
print("Element 3, 1 of Tuple: ",   NestedT[3][1])
print("Element 4, 0 of Tuple: ",   NestedT[4][0])
print("Element 4, 1 of Tuple: ",   NestedT[4][1])
Element 2, 0 of Tuple:  pop
Element 2, 1 of Tuple:  rock
Element 3, 0 of Tuple:  3
Element 3, 1 of Tuple:  4
Element 4, 0 of Tuple:  dance
Element 4, 1 of Tuple:  (1, 2)

เราสามารถใช้เลขดัชนี (Index) ตัวที่สามเข้าถึงข้อมูลสตริงที่เป็นสมาชิกของ Tuple สมาชิกได้เช่นกัน

# แสดงสมาชิกตัวแรกสุดที่อยู่ในสมาชิกลำดับที่ 2 ใน Tuple สมาชิก

NestedT[2][1][0]
'r'
# แสดงสมาชิกตัวที่สองที่อยู่ในสมาชิกลำดับที่ 2 ใน Tuple สมาชิก

NestedT[2][1][1]
'o'

เราสามารถใช้ภาพการแตกรากของต้นไม้แสดงตำแหน่งของสมาชิก โดยตัวเลขดัชนีที่แตกรากออกมาใหม่จะเป็นตำแหน่งของสมาชิกที่อยู่ในระดับที่ลึกลงไป

คำสั่ง 2 บรรทัดข้างต้น สามารถแสดงเป็นภาพได้ดังนี้

นอกจากนี้ เรายังสามารถใช้เลขดัชนี (Index) ตัวที่สามเข้าถึงสมาชิกที่อยู่ลึกเข้าไปใน Tuple ซ้อน Tuple ซ้อน Tuple ได้เช่นกัน

# แสดงสมาชิกตัวแรกที่อยู่ใน Tuple (1,2)

NestedT[4][1][0]
1
# แสดงสมาชิกตัวที่สองที่อยู่ใน Tuple (1,2)

NestedT[4][1][1]
2

รูปต่อไปนี้แสดงความสำพันธ์ระหว่างรากที่แตกออกมากับสมาชิกที่ซ้อนอยู่ใน NestedT[4][1]

\(\qquad\) ในภาษา Python มีชนิดของข้อมูลที่ใช้จัดเก็บและจัดเรียงข้อมูลต่างชนิดกันให้รวมกันเป็นชุดข้อมูลเดียวกัน และใช้ชื่อตัวแปรตัวเดียวกันได้ คือ Tuple กับ List (โดยตัวแปร Tuple ข้อมูลจะอยู่ภายใต้ “( )” แต่ ตัวแปร List ข้อมูลจะอยู่ภายใต้ “[ ]”) แต่สิ่งที่แตกต่างกันคือ Tuple เป็นข้อมูลที่ไม่สามารถเปลี่ยนแปลงได้ (Immutable) หรือกล่าวอีกนัยหนึ่งก็คือ หลังจากที่ประกาศตัวแปรและกำหนดค่าให้กับ Tuple แล้ว มันจะไม่สามารถลบหรือเปลี่ยนแปลงค่าได้ ในขณะที่ List สามารถทำได้ (Mutable)

ตัวอย่างต่อไปนี้เป็นการเปลี่ยนค่า NestedT[4][1][1] จาก 2 เป็น 100 จะเกิดเออเรอร์ (TypeError: ‘tuple’ object does not support item assignment)

NestedT[4][1][1] = 100
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In [44], line 1
----> 1 NestedT[4][1][1] = 100

TypeError: 'tuple' object does not support item assignment

Tuple vs. List ในภาษาไพธอน (สาเหตุที่ใช้ Tuple)#

\(\qquad\) ในภาษาไพธอน ชุดข้อมูลแบบ tuple เป็นชุดข้อมูลที่มีโครงสร้างใกล้เคียงกับ list สามารถเก็บข้อมูลภายในหลายจำนวนในตัวแปรเดียวกัน โดยจัดเก็บข้อมูลตามลำดับ มีการจัดเข้าถึงข้อมูลผ่านการเรียก Index ของชุดข้อมูลภายใน เหมือนกัน

แล้ว… เมื่อใดควรใช้ Tuples เมื่อใดควรใช้ Lists

หากเป็นข้อมูลที่ไม่ต้องการให้เปลี่ยนแปลง คุณควรเลือกประเภทของข้อมูลให้เป็น Tuple แทน List ซึ่งจะเป็นการป้องกันไม่ให้ข้อมูลเปลี่ยนโดยไม่ได้ตั้งใจ

แต่ถ้าเป็นข้อมูลที่จะมีการขยายเพิ่มหรือย่อลดขนาดของข้อมูลระหว่างการรันโปรแกรม คุณต้องใช้ประเภทของข้อมูลเป็น List

\(\qquad\) Tuple ไม่เพียงแค่ถูกใช้ในกรณีที่ต้องการเก็บชุดข้อมูลที่มีลำดับคล้ายกับ List และไม่ต้องการให้ค่าของข้อมูลเปลี่ยนแปลงในภายหลังเท่านั้น แต่ยังถูกใช้ เพื่อเพิ่มประสิทธิภาพในการทำงานของคอมพิวเตอร์ เนื่องจากการใช้ Tuple ช่วยประหยัดหน่วยความจำ (ดูผลลัพธ์เปรียบเทียบได้จากโด้ดด้านล่างนี้) และยังช่วยลดเวลาในการประมวลผล (แม้จะใช้เวลาในการประมวลผลน้อยกว่าเล็กน้อยก็ตาม) ได้อีกด้วย นอกจากนี้ ยังสามารถทำการโคลนนิ่ง (Cloning) ข้อมูล ด้วยคำสั่ง tuple1 = tuple2 ได้ โดยไม่ต้องเป็นกังกลว่าค่าเดิมเปลี่ยนจะถูกเปลี่ยน (เนื่องจากค่าของ Tuple เปลี่ยนแปลงไม่ได้! แต่…ในกรณีของ List คำสั่ง list1 = list2 จะเป็นการก๊อปปี้ (Copy) ไม่ใช่การโคลนนิ่ง ซึ่งอาจจะทำให้ค่าเดิมของ List ถูกเปลี่ยนได้ในภายหลัง!)(รายละเอียดของการก๊อปปี้ (Copy) และการโคลนนิ่ง (Cloning) อยู่ใน Lists)

Note

Tuple ไม่ได้มีเฉพาะในภาษาไพธอน ภาษาคอมพิวเตอร์อื่นๆ ก็มีใช้ เช่น Lisp, Linda, C# ฯลฯ

# โค้ดเปรียบเทียบประสิทธิภาพของหน่วยความจำระหว่าง Tuple กับ List
# โดยใช้ฟังก์ชัน sys.getsizeof() ซึ่งจะคืนค่าเป็นขนาดของหน่วยความจำที่เก็บค่าอ็อบเจ็กต์ มีหน่วยเป็นไบต์ 
# Ref: https://towardsdatascience.com/python-tuples-when-to-use-them-over-lists-75e443f9dcd7

import sys

a_list = [1,2,3,4,5]  # ตัวแปร List
a_tuple = (1,2,3,4,5) # ตัวแปร Typle

print(sys.getsizeof(a_list), 'bytes for the list object.') 
print(sys.getsizeof(a_tuple), 'bytes for the tuple object.') # 
96 bytes for the list object.
80 bytes for the tuple object.

เนื่องจาก Tuple เป็นโครงสร้างข้อมูลประเภท Immutable (เมื่อถูกสร้างขึ้นแล้ว จะเปลี่ยนค่าไม่ได้) จะถูกเก็บไว้ในหน่วยความจำบล็อกเดียว ในขณะที่ List เป็นข้อมูล Mutable (เมื่อถูกสร้างขึ้นแล้ว สามารถเพิ่มหรือลดจำนวนสมาชิก เปลี่ยนค่าข้อมูลได้) จะถูกเก็บไว้ในหน่วยความจำสองบล็อก (หนึ่งบล็อกเป็นบล็อกที่มีขนาดคงที่ และอีกบล็อกสำหรับจัดเก็บข้อมูล มีขนาดที่ไม่คงที่ ปรับขนาดได้ตามต้องการ)

[Exercise]#

1. จาก Tuple ที่กำหนดค่าต่อไปนี้

genres_tuple = ("pop", "rock", "soul", "dance pop", "soft rock", \
                "edm", "brostep", "disco") 

1.1) จงหาขนาดของ Tuple genres_tuple

# เขียนโค้ดด้านล่าง แล้วกด Shift+Enter

1.2) จงเขียนโค้ดเข้าถึงสมาชิกที่มีเลขดัชนีเป็น 3 (สมาชิกที่มีเลขดัชนี 3 มีค่า?)

# เขียนโค้ดด้านล่าง แล้วกด Shift+Enter

1.3) จงทำการตัด (Slicing) เพื่อให้ได้สมาชิกที่เลขดัชนีเป็น 3, 4 และ 5

# เขียนโค้ดด้านล่าง แล้วกด Shift+Enter

1.4) จงหาสมาชิกสามตัวแรกที่อยู่ใน Tuple genres_tuple

# เขียนโค้ดด้านล่าง แล้วกด Shift+Enter

1.5) จงหาสมาชิกตัวสุดท้ายที่อยู่ใน Tuple genres_tuple

# เขียนโค้ดด้านล่าง แล้วกด Shift+Enter

1.6) จงหาเลขดัชนีของ "edm" (edm: electronic dance music)

# เขียนโค้ดด้านล่าง แล้วกด Shift+Enter

2. จงเขียนโค้ดกลับลำดับสมาชิกของ Tuple tuple_a = ("ฉัน", "ชอบ", "เธอ") (เรียงลำดับย้อนกลับ)

# เขียนโค้ดด้านล่าง แล้วกด Shift+Enter

3. จงเขียนโค้ดจัดเรียงลำดับตัวเลขใน Tuple tuple_c = (-5, 1, -3, 9, 3, 6,-1, -3, 6, 2, 8) จากน้อยไปมาก

# เขียนโค้ดด้านล่าง แล้วกด Shift+Enter

Author#

S.C.

Change Log#

Date

Version

Change Description

08-08-2021

0.1

First edition

05-05-2022

0.2

Fix the typo, minor change