การใช้งาน *args และ **kwargs ในภาษา Python

สำหรับคำสั่ง *args และ **kwargs ในภาษา Python ผมเชื่อว่าเพื่อน ๆ ที่ศึกษาภาษา Python ต้องเจอมาแล้วกันทุกคนเป็นอย่างแน่นอน แต่มันคืออะไร ใช้ยังไง ใช้ตอนไหน เดี๋ยววันนี้มา recap กัน
จากโค้ดด้านล่าง ฟังก์ชัน hello_world()
คือการประกาศฟังก์ชันแบบปกติ จะเห็นว่าไม่มีอะไรอยู่ในวงเล็บหรือประกาศพารามิเตอร์ใด ๆ ไว้ แบบนี้เราไม่ต้องส่งอากิวเมนต์ใด ๆ เข้าไปในฟังก์ชัน จะเห็นว่าโค้ดบรรทัดสุดท้ายในฟังก์ชันก็ว่างเปล่าได้เลย
def hello_world():print("Hello world, you all Python guys !!")hello_world() # ฟังก์ชันปกติ ไม่ต้องส่งอากิวเมนต์ใด ๆ เข้าไป
Hello world, you all Python guys !!
Parameter vs Argument
ทีนี้มาดูฟังก์ชันแบบที่มี Parameter และ Argument กันครับ
จากโค้ดด้านล่าง
- พารามิเตอร์:
param1
,param2
(ตัวแปรที่ประกาศไว้ในฟังก์ชัน) - อากิวเมนต์:
1
,2
(ข้อมูลที่ส่งเข้าไปในฟังก์ชันตามจำนวนพารามิเตอร์ที่ประกาศไว้)
def sum_num(param1, param2):sum = param1 + param2return sumprint(sum_num(2, 3)) # ส่งอากิวเมนต์เข้ามาตามพารามิเตอร์ที่ได้ประกาศไว้
Output
5
จากฟังก์ชัน sum_num(...)
ประกาศพารามิเตอร์ไว้สองตัว คือ param1
และ param2
โดยในฟังก์ชันนี้ก็ไม่ได้มีอะไรมาก นำพารามิเตอร์ 2 ตัวนี้มาบวกกันและเก็บไว้ในตัวแปร sum
ซึ่งก็จะได้ 2 + 3 ผลลัพธ์คือ 5 นั่นเอง
แต่ถ้าประกาศพารามิเตอร์ไว้ในฟังก์ชัน แต่ส่งอากิวเมนต์เข้ามาไม่ครบ ?
def sum_num(param1, param2):sum = param1 + param2return sumprint(sum_num(2))
จะได้ error แบบนี้ นั่นก็คือเราประกาศพารามิเตอร์ไว้ 2 ตัวในฟังก์ชันคือ param1 และ param2 แต่ตอนส่งค่าอากิวเมนต์เข้ามา ส่งมาแค่ค่าเดียวคือค่าของ param1 นั่นก็คือ 2
TypeError: sum_num() missing 1 required positional argument: 'param2'
ดังนั้นนี่คือแบบฟิกพารามิเตอร์ เรากำหนดเท่าไหร่ในฟังก์ชัน ก็ต้องส่งค่าหรืออากิวเมนต์เข้ามาให้ครบ (หรือส่งเกินก็ไม่ได้)
*args คืออะไร ?
*args คือ พารามิเตอร์แบบที่ไม่ใช่คีย์เวิร์ด (Non-Keyword Arguments) คือสามารถส่งค่าเข้ามาในฟังก์ชันได้เลย โดยเป็นชนิดข้อมูลแบบ tuple ซึ่งใน *args นั้นจะไม่ได้ฟิกอากิวเมนต์ที่ต้องส่งเข้ามาเหมือนกับพารามิเตอร์ปกติแล้วครับ (จะส่งเข้ามาเท่าไหร่ก็ได้)
ตัวอย่างโค้ด
def hello_guy(*args):for arg in args:print(arg)hello_guy('Hello', 'Mr. Pita', 43) # ส่งเข้ามากี่ตัวก็ได้ (ในตัวอย่างคือ 3 ตัว)
Output
HelloMr. Pita43
จากตัวอย่าง ฟังก์ชัน hello_guy()
สามารถรับอาร์กิวเมนต์ได้หลายตัว
- ประกาศฟังก์ชันชื่อ
hello_guy()
พร้อมประกาศพารามิเตอร์*args
- ลูป
args
ออกมา(เพราะ*args
เป็นประเภทข้อมูลแบบ tuple เลยสามารถรัน for loop ได้เลย) - จากนั้น print แสดงผลออกทางหน้าจอ
- เรียกใช้ฟังก์ชัน โดยในฟังก์ชันรับอากิวเมนต์เข้ามา 3 ตัวคือ
Hello
,Mr. Pita
และ43
เห็นไหมครับว่าเราจะส่งอากิวเมนต์เข้าไปกี่ตัวก็ได้ในฟังก์ชันนี้
Note: การประกาศแบบ *args นั้นข้อสังเกตง่าย ๆ คือมี * (asterisk) 1 ตัวอยู่ข้างหน้า และไม่ต้องเป็นคำว่า *args แบบนี้ก็ได้จะเป็นคำไหนก็ได้โดยให้ใส่ * เพื่อเป็นตัวบ่งบอก (identifier) แต่แนะนำว่าถ้าไม่จำเป็นก็ให้ใช้ตัวนี้แหละครับเพราะมันคือ convention (ธรรมเนียมที่ปฏิบัติกันมา)
**kwargs คืออะไร ?
**kwargs คือ พารามิเตอร์ที่กำหนดไว้เพื่อใช้ส่งอากิวเมนต์เข้ามาในฟังก์ชันแบบไม่ตายตัว ซึ่งมีความคล้ายกันกับ *args แต่ความต่าง คือ อากิวเมนต์ที่ส่งเข้ามาต้องเป็นแบบคีย์เวิร์ด (Keyword Arguments) อาร์กิวเมนต์เหล่านี้จะถูกรับเข้ามาในฟังก์ชันเป็นแบบ dict ( หรือ dictionary) ซึ่งหมายความว่าเราต้องกำหนด Key ให้กับอากิวเมนต์ด้วย แทนที่จะใส่เฉพาะ Value เพียว ๆ
ตัวอย่างโค้ด
def hello_devhub(**kwargs):for key, value in kwargs.items():print(f"{key}: {value}")print(hello_devhub(greeting='Hello', name='Devhub', team_members=3)) # ส่งแบบ key:value
Output
greeting: Helloname: Devhubteam_members: 3
จากตัวอย่าง ฟังก์ชัน hello_devhub()
สามารถรับอาร์กิวเมนต์ได้หลายตัว (แต่ต้องกำหนด Keys ของอากิวเมนต์แต่ละตัวด้วย)
- ประกาศฟังก์ชันชื่อ
hello_devhub()
พร้อมประกาศพารามิเตอร์**kwargs
- ลูป
kwargs
ออกมา (และ**kwargs
เป็นประเภทข้อมูลแบบ dict เลยสามารถรัน for loop ได้เลย) โดยเราสามารถ loop ออกมาได้ทั้ง key และ value ของ Dict โดยดึงค่าออกมาด้วยเมธอด.items()
ซึ่งเป็นหนึ่ง built-in function ของ dict (มีให้อ่านต่อด้านล่าง) - จากนั้น print แสดงผลออกทางหน้าจอ
- เรียกใช้ฟังก์ชัน โดยในฟังก์ชันรับอากิวเมนต์เข้ามา 3 ตัวคือ
greeting="Hello"
name="Dehub"
และteam_members=3
ใจความสำคัญอยู่ที่บรรทัดสุดท้าย จะเห็นว่า **kwargs
นั้นเราต้องใส่ข้อมูลที่เป็นแบบ key:value ซึ่งมันก็คือ Dict นั่นเอง
Note: การประกาศแบบ **kwargs นั้นมีข้อสังเกตง่าย ๆ คือมี ** (asterisks) 2 ตัวอยู่ข้างหน้า และเช่นเดียวกัย *args คือไม่ฟิกตายตัวว่าต้องเป็น **kwargs
สำหรับผู้อ่านที่อยากศึกษาเพิ่มเติมเกี่ยวกับ built-in methods ของ Dict ว่ามีตัวไหนบ้าง ผมก็แนะนำ Python Dictionary - W3schools เลยครับ
Python Dictionary Built-in Methods
การใช้งานร่วมกันระหว่าง *args และ **kwargs
*args และ **kwargs สามารถใช้งานร่วมกันได้ในฟังก์ชันเดียวกัน เพื่อให้ฟังก์ชันนั้นสามารถรับอาร์กิวเมนต์ได้ทั้งแบบไม่มีคีย์เวิร์ดและแบบมีคีย์เวิร์ด
ตัวอย่างโค้ด
def combine_params(*args, **kwargs):for arg in args:print(arg)for key, value in kwargs.items():print(f"{key}: {value}")combine_params('apple', 'banana', first='orange', second='grape')
ในฟังก์ชัน combine_2_params(...)
เป็นการรวมการประกาศพารามิเตอร์ทั้งแบบ *args และ **kwargs เข้ามาใข้งานร่วมกัน
Output
applebananafirst: orangesecond: grape
สรุป
- *args คือ พารามิเตอร์ที่ประกาศไว้ในฟังก์ชัน โดยที่ไม่ได้กำหนดอากิวเมนต์ (ข้อมูลที่ส่งเข้ามา) แบบตายตัว สามารถส่งเข้ามาในฟังก์ชันกี่ตัวก็ได้ เป็นประเภทข้อมูลแบบ Tuple
- **kwargs คือ พารามิเตอร์ที่ประกาศไว้ในฟังก์ชัน คล้ายกันกับ **args เพียงแต่ว่าข้อมูลที่ส่งเข้ามาต้องกำหนดคีย์ของข้อมูลนั้นด้วย เป็นประเภทข้อมูลแบบ Dict (Dictionary)
โดยทั้ง *args และ **kwargs นั้นช่วยทำให้ฟังก์ชันของเรายืดหยุ่นได้เป็นอย่างดี
หวังว่าบทความนี้จะช่วย recap ให้เพื่อน ๆ ได้เข้าใจเกี่ยวกับโครงสร้างและการใช้งาน *args และ **kwargs ในภาษา Python กันมากขึ้นไม่มากก็น้อย ถ้าเห็นคำสั่งนี้แล้วต่อไปก็ไม่ต้องตกใจ และสามารถใช้มันได้อย่างถูกต้องและไม่งงกันครับ ... Happy coding ครับ
เพิ่มเพื่อนใน LINE Official ของ devhub.in.th เพื่อที่จะได้ไม่พลาดทุก ๆ event แจ่ม ๆ ที่จะถึงก่อนใคร