ไวยากรณ์ Python พื้นฐานที่ใช้บ่อยในวิทยาการข้อมูล
ช่วงสองวันนี้ผมได้อ่านหนังสือ Data Science from Scrach (ดาวน์โหลด PDF ได้ที่นี่) ซึ่งเป็นหนังสือแนะนำวิทยาการข้อมูลเบื้องต้นที่ยอดเยี่ยม อ่านเข้าใจง่ายและเข้าถึงได้ทุกคนครับ ในบทหนึ่งของหนังสือได้แนะนำไวยากรณ์พื้นฐานของ Python และไวยากรณ์ขั้นสูงที่ใช้บ่อยในวิทยาการข้อมูล ผมเห็นว่าคำอธิบายทำได้ดี กระชับและเข้าใจง่าย จึงขอแปลและรวบรวมไว้ที่นี่เพื่อเป็นบันทึกช่วยจำครับ
ไวยากรณ์ Python ที่ใช้บ่อยในวิทยาการข้อมูล (พื้นฐาน)
ไวยากรณ์ Python ที่ใช้บ่อยในวิทยาการข้อมูล (ขั้นสูง)
บทนี้จะเน้นการแนะนำไวยากรณ์และฟังก์ชันพื้นฐานของ Python ที่มีประโยชน์อย่างมากในการประมวลผลข้อมูล (อ้างอิงจาก Python 2.7)
รูปแบบการเว้นวรรค
ภาษาโปรแกรมหลายภาษาใช้เครื่องหมายวงเล็บปีกกาเพื่อควบคุมบล็อกโค้ด แต่ Python ใช้วิธีการย่อหน้า (indentation) แทน:
for i in [1, 2, 3, 4, 5]:
print i # บรรทัดแรกของลูป "for i"
for j in [1, 2, 3, 4, 5]:
print j # บรรทัดแรกของลูป "for j"
print i + j # บรรทัดสุดท้ายของลูป "for j"
print i # บรรทัดสุดท้ายของลูป "for i"
print "done looping"
สิ่งนี้ทำให้โค้ด Python อ่านง่ายมาก แต่ก็หมายความว่าคุณต้องให้ความสำคัญกับรูปแบบการจัดวางโค้ดอยู่เสมอ ช่องว่างภายในวงเล็บจะถูกละเว้น ซึ่งมีประโยชน์เมื่อเขียนนิพจน์ที่ยาวๆ:
long_winded_computation = (1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 18 + 19 + 20)
และยังช่วยให้โค้ดอ่านง่ายขึ้นด้วย:
list_of_lists = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
easier_to_read_list_of_lists = [ [1, 2, 3],
[4 ,5 ,6 ],
[7 ,8 ,9 ] ]
คำสั่งหลายบรรทัด
สามารถใช้เครื่องหมายแบ็กสแลช (\) เพื่อเชื่อมต่อสองบรรทัดที่ถูกแบ่งออกจากกัน (วิธีนี้ไม่ค่อยนิยมใช้):
two_plus_three = 2 + \
3
โมดูล (Modules)
ไม่ว่าจะเป็นโมดูลที่มาพร้อมกับ Python หรือโมดูลบุคคลที่สามที่คุณดาวน์โหลดมา คุณจำเป็นต้องนำเข้า (import) โมดูลเหล่านั้นด้วยตนเองก่อนจึงจะสามารถใช้งานได้
- นำเข้าโมดูลทั้งหมดโดยตรงแบบง่ายๆ:
import re
my_regex = re.compile("[0-9]+", re.I)
โมดูล re ที่นำเข้าในที่นี้ใช้สำหรับ Regular Expressions หลังจากนำเข้าโมดูลแล้ว คุณสามารถเรียกใช้ฟังก์ชันเฉพาะได้โดยตรงโดยใช้ชื่อโมดูลเป็นคำนำหน้า (เช่น re.)
- หากชื่อโมดูลที่คุณต้องการนำเข้าถูกใช้ไปแล้วในโค้ด คุณสามารถแมปโมดูลนั้นให้เป็นชื่ออื่นได้เมื่อนำเข้า:
import re as regex
my_regex = regex.compile("[0-9]+", regex.I)
- ถ้าคุณเป็นคนไม่ดี คุณสามารถนำเข้าโมดูลทั้งหมดเข้าสู่เนมสเปซปัจจุบันได้ ซึ่งอาจทำให้เกิดการเขียนทับตัวแปรที่คุณได้นิยามไว้แล้วโดยไม่ตั้งใจ:
match = 10
from re import * # โมดูล re มีฟังก์ชัน match
print match # แสดงผลฟังก์ชัน match
แต่เนื่องจากคุณเป็นคนดี ผมเชื่อว่าคุณจะไม่ทำเช่นนั้น
การคำนวณเลขคณิต (Arithmetic)
Python 2.7 ใช้การหารแบบจำนวนเต็ม (integer division) เป็นค่าเริ่มต้น ดังนั้น $ 5 / 2 = 2 $ แต่บ่อยครั้งเราไม่ต้องการผลลัพธ์ที่เป็นจำนวนเต็ม จึงสามารถนำเข้าโมดูลนี้ได้:
from __future__ import division
หลังจากนำเข้าแล้ว จะได้ $5 / 2 = 2.5$.
การหารแบบจำนวนเต็ม: $5 // 2 = 2$.
ฟังก์ชัน (Functions)
การนิยามฟังก์ชัน
ฟังก์ชันคือชุดคำสั่งที่มีหน้าที่รับอินพุต 0 ตัวขึ้นไป และส่งคืนเอาต์พุตตามที่กำหนด ใน Python เรานิยามฟังก์ชันโดยใช้ def ชื่อฟังก์ชัน(พารามิเตอร์):
def double(x):
"""คุณสามารถเขียนคำอธิบายเกี่ยวกับฟังก์ชันได้ที่นี่
เช่น ฟังก์ชันนี้จะนำอินพุตมาคูณด้วย 2"""
# ส่วนนี้คือตัวฟังก์ชัน อย่าลืมย่อหน้าให้ถูกต้อง
return x * 2
การใช้งานฟังก์ชัน
ใน Python ฟังก์ชันถือเป็น “First-Class Citizen” ซึ่งหมายความว่าเราสามารถกำหนดฟังก์ชันให้กับตัวแปร หรือส่งฟังก์ชันเป็นพารามิเตอร์ไปยังฟังก์ชันอื่นได้:
def apply_to_one(f):
"""เรียกใช้ฟังก์ชัน f และส่ง 1 เป็นพารามิเตอร์ให้กับฟังก์ชัน"""
return f(1)
my_double = double # double ชี้ไปยังฟังก์ชันที่นิยามไว้ในหัวข้อก่อนหน้า
x = apply_to_one(my_double) # x จะมีค่าเท่ากับ 2
ฟังก์ชันนิรนาม (Lambda Functions)
เรายังสามารถสร้างฟังก์ชันนิรนาม (anonymous function) โดยใช้ lambda ได้อีกด้วย:
y = apply_to_one(lambda x: x + 4) # มีค่าเท่ากับ 5
สามารถกำหนด lambda ให้กับตัวแปรอื่นได้ แต่คนส่วนใหญ่แนะนำให้ใช้ def มากกว่า:
another_double = lambda x: 2 * x # ไม่แนะนำ
def another_double(x): return 2 * x # วิธีที่แนะนำ
เพิ่มเติม:
lambdaเป็นเพียงนิพจน์ (expression) เท่านั้น ทำให้ตัวฟังก์ชันง่ายกว่าdefมาก- ส่วนหลักของ
lambdaคือนิพจน์ ไม่ใช่บล็อกโค้ด ทำให้สามารถรวมตรรกะเข้าไปในนิพจน์lambdaได้อย่างจำกัดเท่านั้น
การส่งผ่านพารามิเตอร์ฟังก์ชัน
พารามิเตอร์ฟังก์ชันสามารถกำหนดค่าเริ่มต้นได้ หากเรียกใช้ฟังก์ชันโดยไม่ระบุพารามิเตอร์ จะใช้ค่าเริ่มต้น แต่ถ้าระบุพารามิเตอร์ จะใช้ค่าที่ส่งผ่านไป:
def my_print(message="my default message"):
print message
my_print("hello") # แสดงผล "hello"
my_print() # แสดงผล "my default message"
บางครั้งการระบุพารามิเตอร์โดยใช้ชื่อพารามิเตอร์โดยตรงก็มีประโยชน์มากเช่นกัน:
def subtract(a=0, b=0):
return a - b
subtract(10, 5) # คืนค่า 5
subtract(0, 5) # คืนค่า -5
subtract(b=5) # เหมือนกับตัวอย่างก่อนหน้า คืนค่า -5
สตริง (Strings)
สามารถใช้เครื่องหมายคำพูดเดี่ยว (’) หรือคู่ (”) เพื่อสร้างสตริงได้ (เครื่องหมายคำพูดต้องจับคู่กันเสมอ):
single_quoted_string = 'data science'
double_quoted_string = "data science"
ใช้เครื่องหมายแบ็กสแลช (\) เพื่อแสดงอักขระพิเศษ (escape character) เช่น:
tab_string = "\t" # แสดงถึงอักขระแท็บ (tab)
len(tab_string) # มีค่าเท่ากับ 1
เมื่อคุณต้องการใช้เครื่องหมายแบ็กสแลชเอง (เช่น สำหรับพาธใน Windows หรือ Regular Expressions) คุณสามารถกำหนดสตริงแบบดิบ (raw string) โดยใช้ r"" ได้:
not_tab_string = r"\t" # แสดงถึงอักขระ '\' และ 't'
len(not_tab_string) # มีค่าเท่ากับ 2
ใช้เครื่องหมายคำพูดคู่สามตัวเพื่อสร้างสตริงหลายบรรทัด:
multi_line_string = """นี่คือบรรทัดแรก
นี่คือบรรทัดที่สอง
นี่คือบรรทัดที่สาม"""
การจัดการข้อยกเว้น (Exception Handling)
เมื่อโปรแกรมเกิดข้อผิดพลาด Python จะสร้าง ข้อยกเว้น (exception) หากเราไม่จัดการกับมัน โปรแกรมจะหยุดการทำงาน การดักจับข้อยกเว้นสามารถทำได้โดยใช้คำสั่ง try และ except:
try:
print 0 / 0
except ZeroDivisionError:
print "ไม่สามารถหารด้วย 0 ได้"
แม้ว่าในภาษาโปรแกรมอื่น ๆ ข้อยกเว้นจะถูกมองว่าเป็นสิ่งที่ไม่ดี แต่ใน Python การจัดการข้อยกเว้นจำนวนมากจะทำให้โค้ดของคุณกระชับและสะอาดขึ้น
ลิสต์ (Lists)
การสร้างลิสต์
ลิสต์คือชุดข้อมูลที่มีการจัดเรียงลำดับอย่างง่าย และเป็นโครงสร้างข้อมูลพื้นฐานที่สุดใน Python (คล้ายกับ array ในภาษาอื่น แต่ลิสต์มีคุณสมบัติเพิ่มเติมบางอย่าง) การสร้างลิสต์:
integer_list = [1, 2, 3]
heterogeneous_list = ["string", 0.1, True]
list_of_lists = [ integer_list, heterogeneous_list, [] ]
list_length = len(integer_list) # มีค่าเท่ากับ 3
list_sum = sum(integer_list) # มีค่าเท่ากับ 6
การเข้าถึงค่าในลิสต์
คุณสามารถเข้าถึงค่าในลิสต์โดยใช้อินเด็กซ์ในวงเล็บเหลี่ยม:
x = range(10) # ลิสต์ x จะได้ค่าเป็น [0, 1, ..., 9]
zero = x[0] # มีค่าเท่ากับ 0, ลิสต์จะเริ่มต้นที่อินเด็กซ์ 0
one = x[1] # มีค่าเท่ากับ 1
nine = x[-1] # มีค่าเท่ากับ 9, คือสมาชิกตัวสุดท้ายในลิสต์
eight = x[-2] # มีค่าเท่ากับ 8, คือสมาชิกตัวที่สองจากท้ายในลิสต์
x[0] = -1 # ตอนนี้ลิสต์ x จะเป็น [-1, 1, 2, 3, ..., 9]
การแบ่งส่วนลิสต์ (Slicing)
สามารถแบ่งส่วนลิสต์โดยใช้วงเล็บเหลี่ยมได้:
first_three = x[:3] # [-1, 1, 2]
three_to_end = x[3:] # [3, 4, ..., 9]
one_to_four = x[1:5] # [1, 2, 3, 4]
last_three = x[-3:] # [7, 8, 9]
without_first_and_last = x[1:-1] # [1, 2, ..., 8]
copy_of_x = x[:] # [-1, 1, 2, ..., 9]
สามารถใช้ in เพื่อตรวจสอบว่ามีสมาชิกอยู่ในลิสต์หรือไม่:
1 in [1, 2, 3] # True
0 in [1, 2, 3] # False
วิธีการค้นหาสมาชิกแบบนี้มีประสิทธิภาพต่ำ ควรใช้ก็ต่อเมื่อลิสต์มีขนาดเล็กมาก หรือคุณไม่ใส่ใจเรื่องเวลาในการค้นหา
การรวมลิสต์
ใน Python การรวมลิสต์สองรายการเข้าด้วยกันทำได้ง่ายมาก:
x = [1, 2, 3]
x.extend([4, 5, 6]) # ตอนนี้ x จะเป็น [1,2,3,4,5,6]
หากคุณไม่ต้องการแก้ไขลิสต์ x เดิม คุณสามารถใช้โอเปอเรเตอร์ ’+’ เพื่อสร้างลิสต์ใหม่ได้:
x = [1, 2, 3]
y = x + [4, 5, 6] # ตอนนี้ y จะเป็น [1, 2, 3, 4, 5, 6]; x ไม่มีการเปลี่ยนแปลง
มักจะใช้วิธีนี้ในการเพิ่มสมาชิกทีละหนึ่งตัวในลิสต์:
x = [1, 2, 3]
x.append(0) # ตอนนี้ x จะเป็น [1, 2, 3, 0]
y = x[-1] # มีค่าเท่ากับ 0
z = len(x) # มีค่าเท่ากับ 4
การแยกส่วนลิสต์ (Unpacking)
หากคุณทราบจำนวนสมาชิกในลิสต์ การแยกส่วนลิสต์นั้นทำได้ง่ายมาก:
x, y = [1, 2] # ตอนนี้ x = 1, y = 2
หากจำนวนสมาชิกทั้งสองข้างของสมการไม่ตรงกัน คุณจะได้รับข้อผิดพลาด ValueError ดังนั้น เราจึงมักใช้เครื่องหมายขีดล่าง (underscore) เพื่อเก็บส่วนที่เหลือของลิสต์:
_, y = [1, 2] # ตอนนี้ y == 2, โดยไม่สนใจสมาชิกตัวแรก
ทูเพิล (Tuples)
ลิสต์และทูเพิลมีความคล้ายคลึงกัน ข้อแตกต่างเพียงอย่างเดียวคือ สมาชิกในทูเพิลไม่สามารถเปลี่ยนแปลงได้
การสร้างทูเพิล
สามารถสร้างทูเพิลโดยใช้วงเล็บกลม หรือไม่ใช้วงเล็บเลยก็ได้:
my_tuple = (1, 2)
other_tuple = 3, 4
my_list[1] = 3 # ตอนนี้ my_list จะเป็น [1, 3]
try:
my_tuple[1] = 3
except TypeError:
print "ไม่สามารถแก้ไขทูเพิลได้"
การใช้ทูเพิลทำให้การรับค่าคืนหลายค่าจากฟังก์ชันทำได้สะดวกมาก:
def sum_and_product(x, y):
return (x + y),(x * y)
sp = sum_and_product(2, 3) # มีค่าเท่ากับ (5, 6)
s, p = sum_and_product(5, 10) # s = 15, p = 50
ทูเพิล (และลิสต์) รองรับการกำหนดค่าหลายสมาชิกพร้อมกัน:
x, y = 1, 2 # ตอนนี้ x = 1, y = 2
x, y = y, x # การสลับค่าระหว่างสองตัวแปรใน Python; ตอนนี้ x = 2, y = 1
พจนานุกรม (Dictionaries)
การสร้างพจนานุกรม
โครงสร้างข้อมูลพื้นฐานอีกอย่างใน Python คือพจนานุกรม (dictionary) ซึ่งช่วยให้คุณสามารถเข้าถึงค่า (value) ที่ต้องการได้อย่างรวดเร็วผ่านคีย์ (key) ที่เกี่ยวข้อง:
empty_dict = {} # การนิยามพจนานุกรมว่างเปล่าแบบ Pythonic
empty_dict2 = dict() # การนิยามพจนานุกรมว่างเปล่าแบบไม่ค่อย Pythonic
grades = { "Joel" : 80, "Tim" : 95 } # การจัดเก็บพจนานุกรม
การค้นหาข้อมูลในพจนานุกรม
คุณสามารถใช้คีย์ในวงเล็บเหลี่ยมเพื่อค้นหาค่าที่เกี่ยวข้องได้:
joels_grade = grades["Joel"] # มีค่าเท่ากับ 80
หากคีย์ที่ต้องการค้นหาไม่อยู่ในพจนานุกรม จะเกิด KeyError:
try:
kates_grade = grades["Kate"]
except KeyError:
print "ไม่มีคะแนนสำหรับ Kate!"
สามารถใช้ in เพื่อตรวจสอบว่าคีย์อยู่ในพจนานุกรมหรือไม่:
joel_has_grade = "Joel" in grades # True
kate_has_grade = "Kate" in grades # False
พจนานุกรมมีเมธอดที่สามารถคืนค่าเริ่มต้นได้ ซึ่งเมื่อคีย์ที่ต้องการค้นหาไม่อยู่ในพจนานุกรม จะคืนค่าเริ่มต้นที่กำหนดไว้ (แทนที่จะเกิดข้อยกเว้น):
joels_grade = grades.get("Joel", 0) # มีค่าเท่ากับ 80
kates_grade = grades.get("Kate", 0) # มีค่าเท่ากับ 0
no_ones_grade = grades.get("No One") # คืนค่าเริ่มต้นเป็น None
การแก้ไขพจนานุกรม
สามารถใช้วงเล็บเหลี่ยมเพื่อสร้างหรือแก้ไขคู่คีย์-ค่าในพจนานุกรมได้:
grades["Tim"] = 99 # แทนที่ค่าเดิม
grades["Kate"] = 100 # เพิ่มคู่คีย์-ค่าใหม่
num_students = len(grades) # มีค่าเท่ากับ 3
เราจะใช้พจนานุกรมในลักษณะนี้บ่อยครั้งเพื่อแสดงโครงสร้างของข้อมูล:
tweet = {
"user" : "joelgrus",
"text" : "Data Science is Awesome",
"retweet_count" : 100,
"hashtags" : ["#data", "#science", "#datascience", "#awesome", "#yolo"]
}
นอกจากการค้นหาคีย์เฉพาะแล้ว เรายังสามารถดำเนินการกับคีย์ทั้งหมดได้ดังนี้:
tweet_keys = tweet.keys() # ได้ลิสต์ของคีย์
tweet_values = tweet.values() # ได้ลิสต์ของค่า
tweet_items = tweet.items() # ได้ทูเพิล (คีย์, ค่า)
"user" in tweet_keys # คืนค่า True, เป็นการค้นหาด้วย in ในลิสต์ซึ่งมีประสิทธิภาพต่ำกว่า
"user" in tweet # วิธีที่ Pythonic กว่า, เป็นการค้นหาด้วย in ในพจนานุกรมซึ่งมีประสิทธิภาพสูง
"joelgrus" in tweet_values # True
คีย์ในพจนานุกรมจะต้องไม่ซ้ำกัน และลิสต์ไม่สามารถใช้เป็นคีย์ในพจนานุกรมได้ หากคุณต้องการคีย์ที่มีหลายส่วน คุณสามารถใช้ทูเพิล หรือแปลงคีย์ให้เป็นสตริงด้วยวิธีใดวิธีหนึ่ง
พจนานุกรมดีฟอลต์ (defaultdict)
หากคุณกำลังพยายามนับความถี่ของแต่ละคำที่ปรากฏในเอกสาร วิธีที่ชัดเจนคือการสร้างพจนานุกรม โดยให้คำเป็นคีย์และความถี่เป็นค่า จากนั้นวนลูปผ่านเอกสาร หากเจอคำที่เคยปรากฏแล้วก็เพิ่มค่าความถี่ในพจนานุกรมนั้น 1 หากเจอคำที่ไม่เคยปรากฏก็เพิ่มคู่คีย์-ค่าใหม่เข้าไปในพจนานุกรม:
word_counts = {}
for word in document:
if word in word_counts:
word_counts[word] += 1
else:
word_counts[word] = 1
แน่นอน คุณยังสามารถใช้วิธี ‘ลองดูก่อนแล้วค่อยจัดการ’ เพื่อจัดการกับคีย์ที่หายไปล่วงหน้าได้ดังนี้:
word_counts = {}
for word in document:
try:
word_counts[word] += 1
except KeyError:
word_counts[word] = 1
วิธีที่สามคือการใช้เมธอด get ซึ่งเมธอดนี้ทำงานได้ดีเยี่ยมในการจัดการกับคีย์ที่หายไป:
word_counts = {}
for word in document:
previous_count = word_counts.get(word, 0)
word_counts[word] = previous_count + 1
พจนานุกรมดีฟอลต์ (defaultdict) ทำงานเหมือนพจนานุกรมทั่วไป ข้อแตกต่างเพียงอย่างเดียวคือ เมื่อคุณพยายามค้นหาคีย์ที่ไม่มีอยู่ในพจนานุกรม พจนานุกรมดีฟอลต์จะใช้คีย์ที่คุณให้มาเพื่อสร้างคู่คีย์-ค่าใหม่โดยอัตโนมัติ ในการใช้พจนานุกรมดีฟอลต์ คุณต้องนำเข้าไลบรารี collections:
from collections import defaultdict
word_counts = defaultdict(int) # int() สร้างค่า 0
for word in document:
word_counts[word] += 1
พจนานุกรมดีฟอลต์ยังใช้งานได้ดีกับลิสต์ พจนานุกรมทั่วไป หรือแม้แต่ฟังก์ชันที่คุณกำหนดเอง:
dd_list = defaultdict(list) # list() สร้างลิสต์ว่างเปล่า
dd_list[2].append(1) # ตอนนี้ dd_list จะเป็น {2: [1]}
dd_dict = defaultdict(dict) # dict() สร้างพจนานุกรมว่างเปล่า
dd_dict["Joel"]["City"] = "Seattle" # ตอนนี้ dd_dict จะมีเนื้อหาเป็น { "Joel" : { "City" : "Seattle"}}
dd_pair = defaultdict(lambda: [0, 0]) # สร้างพจนานุกรมที่มีค่าสำหรับคีย์เป็นลิสต์
dd_pair[2][1] = 1 # ตอนนี้ dd_pair จะมีเนื้อหาเป็น {2: [0,1]}
วิธีนี้มีประโยชน์มาก ทำให้ในอนาคตเมื่อเราต้องการดึงค่าจากพจนานุกรม เราไม่จำเป็นต้องตรวจสอบว่าคีย์นั้นมีอยู่หรือไม่
ตัวนับ (Counter)
Counter สามารถแปลงกลุ่มค่าให้เป็นวัตถุที่มีลักษณะคล้ายพจนานุกรมได้โดยตรง โดยที่คีย์จะเป็นสมาชิกในกลุ่มนั้น และค่าที่เกี่ยวข้องคือจำนวนครั้งที่สมาชิกนั้นปรากฏขึ้น ซึ่งมักใช้บ่อยในการสร้างฮิสโตแกรม:
from collections import Counter
c = Counter([0, 1, 2, 0]) # c (ประมาณ) เท่ากับ { 0 : 2, 1 : 1, 2 : 1 }
ด้วยวิธีนี้ เราก็จะมีวิธีที่สะดวกสบายในการนับความถี่ของคำ:
word_counts = Counter(document)
Counter ยังมีเมธอดที่ใช้บ่อยมากคือ most_common ซึ่งสามารถดึงคำที่มีความถี่สูงสุดและจำนวนครั้งที่ปรากฏได้โดยตรง:
# แสดงผลคำที่มีความถี่สูงสุด 10 อันดับแรกพร้อมจำนวนนับ
for word, count in word_counts.most_common(10):
print word, count
เซ็ต (Sets)
โครงสร้างข้อมูลอีกประเภทหนึ่งใน Python คือเซ็ต (set) ซึ่งเป็นชุดของสมาชิกที่ไม่ซ้ำกัน
สามารถสร้างเซ็ตและเพิ่มสมาชิกเข้าไปได้ดังนี้:
s = set()
s.add(1) # s คือ { 1 }
s.add(2) # s คือ { 1, 2 }
s.add(2) # s คือ { 1, 2 }
x = len(s) # มีค่าเท่ากับ 2
y = 2 in s # มีค่าเป็น True
z = 3 in s # มีค่าเป็น False
เหตุผลหลักสองประการในการใช้เซ็ต:
ประการแรก การดำเนินการ in ในเซ็ตมีประสิทธิภาพสูงมาก เมื่อจำนวนสมาชิกในชุดข้อมูลมีขนาดใหญ่มาก การค้นหาสมาชิกในรูปแบบของเซ็ตย่อมเหมาะสมกว่าลิสต์อย่างเห็นได้ชัด:
stopwords_list = ["a","an","at"] + hundreds_of_other_words + ["yet", "you"]
"zip" in stopwords_list # ล้มเหลว, ต้องตรวจสอบสมาชิกแต่ละตัว
stopwords_set = set(stopwords_list)
"zip" in stopwords_set # ค้นหาสำเร็จ และรวดเร็วมาก
ประการที่สอง การใช้เซ็ตเพื่อดึงสมาชิกที่ไม่ซ้ำกันจากชุดข้อมูลทำได้สะดวกมาก:
item_list = [1, 2, 3, 1, 2, 3]
num_items = len(item_list) # 6
item_set = set(item_list) # {1, 2, 3}
num_distinct_items = len(item_set) # 3
distinct_item_list = list(item_set) # [1, 2, 3]
แต่ในความเป็นจริง ความถี่ในการใช้เซ็ตก็ยังไม่สูงเท่าพจนานุกรมและลิสต์
คำสั่งเงื่อนไข
ในภาษาโปรแกรมส่วนใหญ่ คุณสามารถใช้ if เพื่อสร้างเงื่อนไขได้ดังนี้:
if 1 > 2:
message = "if only 1 were greater than two…"
elif 1 > 3:
message = "elif stands for 'else if'"
else:
message = "when all else fails use else (if you want to)"
คุณยังสามารถเขียนคำสั่งเงื่อนไขในบรรทัดเดียวได้ดังนี้ แต่วิธีนี้ไม่ค่อยนิยมใช้:
parity = "even" if x % 2 == 0 else "odd"
คำสั่งวนซ้ำ
ลูป while
ลูป while ใน Python:
x = 0
while x < 10:
print x, "is less than 10"
x += 1
ลูป for
ที่นิยมใช้มากกว่าคือลูป for-in:
for x in range(10):
print x, "is less than 10"
นิพจน์ตรรกะที่ซับซ้อนขึ้นสามารถใช้คำสั่ง continue และ break ได้:
for x in range(10):
if x == 3:
continue # ข้ามไปรอบการทำงานถัดไปทันที
if x == 5:
break # ออกจากลูปทั้งหมด
print x
ผลลัพธ์ที่ได้คือ 0, 1, 2 และ 4
ค่าความจริง (Truthiness)
ตัวแปรบูลีน (Booleans) ใน Python มีการใช้งานคล้ายกับภาษาอื่น ๆ ข้อแตกต่างเพียงอย่างเดียวคือตัวอักษรแรกต้องเป็นตัวพิมพ์ใหญ่เสมอ:
one_is_less_than_two = 1 < 2 # เป็น True
true_equals_false = True == False # เป็น False
Python ใช้ None เพื่อแสดงว่าไม่มีค่า คล้ายกับ null ในภาษาอื่น ๆ:
x = None
print x == None # แสดงผล True, แต่ไม่ค่อยสวยงาม
print x is None # แสดงผล True, ดูดีกว่า
Python อนุญาตให้คุณใช้ค่าอื่น ๆ แทนค่าบูลีนได้ โดยค่าต่อไปนี้ทั้งหมดถือว่าเทียบเท่ากับ False:
- False
- None
- [] (ลิสต์ว่างเปล่า)
- {} (พจนานุกรมว่างเปล่า)
- "" (สตริงว่างเปล่า)
- set() (เซ็ตว่างเปล่า)
- 0
- 0.0
ในทำนองเดียวกัน ก็มีค่าที่เทียบเท่ากับ True อีกมากมาย ซึ่งทำให้คุณสะดวกในการตรวจสอบลิสต์ว่าง สตริงว่าง หรือพจนานุกรมว่าง เป็นต้น
แน่นอนว่า หากคุณไม่สามารถคาดการณ์ผลลัพธ์ได้ อาจเกิดข้อผิดพลาดระหว่างการใช้งาน:
s = some_function_that_returns_a_string()
if s:
first_char = s[0]
else:
first_char = ""
วิธีที่ง่ายกว่าและให้ผลลัพธ์เดียวกันกับวิธีข้างต้นคือ:
first_char = s and s[0]
หากค่าแรกเป็นจริง จะคืนค่าที่สอง มิฉะนั้นจะคืนค่าแรก
ในทำนองเดียวกัน หาก x อาจเป็นตัวเลขหรือเป็นค่าว่าง วิธีนี้จะช่วยให้ได้ x ที่เป็นตัวเลขอย่างแน่นอน:
safe_x = x or 0
ใน Python ยังมีฟังก์ชัน all ซึ่งจะคืนค่า True เมื่อทุกสมาชิกเป็น True และฟังก์ชัน any ซึ่งจะคืนค่า True หากมีสมาชิกอย่างน้อยหนึ่งตัวเป็น True ตัวอย่างเช่น สำหรับลิสต์ที่ทุกสมาชิกเป็น ‘จริง’ ฟังก์ชัน all จะคืนค่า True มิฉะนั้นจะคืนค่า False:
all([True, 1, { 3 }]) # True
all([True, 1, {}]) # False, เพราะ {} เทียบเท่ากับ 'False'
any([True, 1, {}]) # True
all([]) # True, เพราะไม่มีสมาชิกใดที่เทียบเท่ากับ 'False'
any([]) # False, เพราะไม่มีสมาชิกใดที่เทียบเท่ากับ 'True'
อ่านเพิ่มเติม:
ไวยากรณ์ Python ที่ใช้บ่อยในวิทยาการข้อมูล (ขั้นสูง)