Thanks to visit codestin.com
Credit goes to www.datacamp.com

ข้ามไปยังเนื้อหาหลัก

ฟังก์ชันใน Python: วิธีเรียกใช้และเขียนฟังก์ชัน

ค้นพบวิธีเขียนฟังก์ชัน Python ที่นำกลับมาใช้ซ้ำและมีประสิทธิภาพ เชี่ยวชาญพารามิเตอร์ คำสั่ง return และหัวข้อขั้นสูงอย่างฟังก์ชันแลมบ์ดา จัดโค้ดให้เป็นระเบียบยิ่งขึ้นด้วย main() และแนวปฏิบัติที่ดีอื่น ๆ
อัปเดตแล้ว 18 พ.ค. 2569  · 14 นาที อ่าน
แบนเนอร์ทักษะ Python เพื่อสร้างอาชีพกับ DataCamp

ฟังก์ชันเป็นส่วนสำคัญของภาษาโปรแกรม Python: อาจเคยพบและใช้งานฟังก์ชันมากมายที่มีมาให้ในภาษา Python หรือที่มาพร้อมระบบนิเวศไลบรารี อย่างไรก็ตาม ในฐานะนักวิทยาศาสตร์ข้อมูล จะต้องเขียนฟังก์ชันของตนเองอยู่เสมอเพื่อแก้ปัญหาที่เกิดจากข้อมูลของคุณ 

บทช่วยสอนนี้ใช้ไวยากรณ์ Python 3 ตัวอย่างทั้งหมดทำงานบน Python 3.10+ และได้รับการอัปเดตให้สะท้อนแนวปฏิบัติสมัยใหม่แล้ว (f-strings, type hints, พารามิเตอร์แบบ positional-only และ keyword-only) เวอร์ชันเสถียรปัจจุบันคือ Python 3.14

หากต้องการรันโค้ดตัวอย่างทั้งหมดในบทช่วยสอนนี้ได้อย่างง่ายดาย สามารถสร้างสมุดงาน DataLab ได้ฟรี ที่ติดตั้ง Python ไว้ล่วงหน้าและมีโค้ดตัวอย่างทั้งหมด สำหรับการฝึกเขียนฟังก์ชัน Python เพิ่มเติม ลองดูแบบฝึกหัดเชิงปฏิบัติของ DataCamp นี้ หรือเรียนคอร์ส Python Data Science Toolbox!

ฟังก์ชันใน Python

ในการเขียนโปรแกรมจะใช้ฟังก์ชันเพื่อรวมชุดคำสั่งที่ต้องการใช้ซ้ำ หรือที่เนื่องจากความซับซ้อนแล้วควรแยกเป็นโปรแกรมย่อยและเรียกใช้เมื่อจำเป็น นั่นหมายความว่าฟังก์ชันคือส่วนของโค้ดที่เขียนขึ้นเพื่อทำงานตามที่ระบุไว้ เพื่อทำงานนั้น ฟังก์ชันอาจต้องการหรือไม่ต้องการอินพุตหลายตัวก็ได้ เมื่อทำงานเสร็จ ฟังก์ชันอาจคืนค่าหนึ่งค่าหรือหลายค่าก็ได้

ใน Python มีฟังก์ชันอยู่สามประเภท:

  • ฟังก์ชันที่มีมาให้แล้ว (Built-in) เช่น help() เพื่อขอความช่วยเหลือ, min() เพื่อหาค่าต่ำสุด, print() เพื่อพิมพ์วัตถุไปยังเทอร์มินัล เป็นต้น สามารถดูภาพรวมของฟังก์ชันเหล่านี้เพิ่มเติมได้ ที่นี่

  • ฟังก์ชันที่ผู้ใช้กำหนดเอง (User-Defined Functions: UDFs) คือฟังก์ชันที่ผู้ใช้สร้างขึ้นเพื่อช่วยงานของตน และ

  • ฟังก์ชันนิรนาม ซึ่งเรียกอีกอย่างว่าฟังก์ชันแลมบ์ดา เพราะไม่ได้ประกาศด้วยคีย์เวิร์ดมาตรฐาน def

ฟังก์ชัน vs เมธอด

เมธอดหมายถึงฟังก์ชันที่เป็นส่วนหนึ่งของคลาส ต้องเข้าถึงผ่านอินสแตนซ์หรืออ็อบเจ็กต์ของคลาส ฟังก์ชันไม่มีข้อจำกัดนี้: เป็นฟังก์ชันแบบสแตนด์อโลน นั่นหมายความว่าเมธอดทุกตัวเป็นฟังก์ชัน แต่ฟังก์ชันไม่ใช่เมธอดเสมอไป

พิจารณาตัวอย่างนี้ ที่กำหนดฟังก์ชัน plus() ก่อน จากนั้นกำหนดคลาส Summation พร้อมเมธอด sum():

eyJsYW5ndWFnZSI6InB5dGhvbiIsInNhbXBsZSI6IiMgRGVmaW5lIGEgZnVuY3Rpb24gYHBsdXMoKWBcbmRlZiBwbHVzKGEsYik6XG4gIHJldHVybiBhICsgYlxuICBcbiMgQ3JlYXRlIGEgYFN1bW1hdGlvbmAgY2xhc3NcbmNsYXNzIFN1bW1hdGlvbihvYmplY3QpOlxuICBkZWYgc3VtKHNlbGYsIGEsIGIpOlxuICAgIHNlbGYuY29udGVudHMgPSBhICsgYlxuICAgIHJldHVybiBzZWxmLmNvbnRlbnRzICJ9

หากต้องการเรียกใช้เมธอด sum() ที่เป็นส่วนหนึ่งของคลาส Summation จะต้องนิยามอินสแตนซ์หรืออ็อบเจ็กต์ของคลาสนั้นก่อน มาสร้างอ็อบเจ็กต์ดังกล่าวกัน:

eyJsYW5ndWFnZSI6InB5dGhvbiIsInByZV9leGVyY2lzZV9jb2RlIjoiZGVmIHBsdXMoYSxiKTpcbiAgcmV0dXJuIGEgKyBiXG4gIFxuY2xhc3MgU3VtbWF0aW9uKG9iamVjdCk6XG4gIGRlZiBzdW0oc2VsZiwgYSwgYik6XG4gICAgc2VsZi5jb250ZW50cyA9IGEgKyBiXG4gICAgcmV0dXJuIHNlbGYuY29udGVudHMgIiwic2FtcGxlIjoiIyBJbnN0YW50aWF0ZSBgU3VtbWF0aW9uYCBjbGFzcyB0byBjYWxsIGBzdW0oKWBcbnN1bUluc3RhbmNlID0gU3VtbWF0aW9uKClcbnN1bUluc3RhbmNlLnN1bSgxLDIpIn0=

จำไว้ว่าการสร้างอินสแตนซ์นี้ไม่จำเป็นเมื่อจะเรียกใช้ฟังก์ชัน plus() สามารถรัน plus(1,2) ในส่วนโค้ด DataCamp Light ได้โดยไม่มีปัญหา!

พารามิเตอร์ vs อาร์กิวเมนต์

พารามิเตอร์คือชื่อที่ใช้เมื่อกำหนดฟังก์ชันหรือเมธอด และจะถูกแมปกับอาร์กิวเมนต์ กล่าวอีกนัยหนึ่ง อาร์กิวเมนต์คือสิ่งที่ส่งให้กับการเรียกใช้ฟังก์ชันหรือเมธอด ขณะที่โค้ดของฟังก์ชันหรือเมธอดจะอ้างถึงอาร์กิวเมนต์เหล่านั้นด้วยชื่อพารามิเตอร์

พิจารณาตัวอย่างต่อไปนี้และย้อนกลับไปดูส่วน DataCamp Light ด้านบน: คุณส่งอาร์กิวเมนต์สองตัวไปยังเมธอด sum() ของคลาส Summation แม้ว่าก่อนหน้านี้จะกำหนดพารามิเตอร์ไว้สามตัว ได้แก่ self, a และ b

self หายไปไหน?

อาร์กิวเมนต์ตัวแรกของเมธอดในคลาสทุกตัวจะเป็นการอ้างอิงไปยังอินสแตนซ์ปัจจุบันของคลาส ซึ่งในที่นี้คือ Summation ตามธรรมเนียมจะเรียกอาร์กิวเมนต์นี้ว่า self

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

วิธีนิยามฟังก์ชัน: ฟังก์ชันที่ผู้ใช้กำหนดเอง (UDFs)

สี่ขั้นตอนในการนิยามฟังก์ชันใน Python มีดังนี้:

  1. ใช้คีย์เวิร์ด def เพื่อประกาศฟังก์ชัน แล้วตามด้วยชื่อฟังก์ชัน

  2. เพิ่มพารามิเตอร์ให้กับฟังก์ชัน: ควรอยู่ในวงเล็บของฟังก์ชัน ลงท้ายบรรทัดด้วยโคลอน

  3. เพิ่มคำสั่งที่ฟังก์ชันควรดำเนินการ

  4. จบฟังก์ชันด้วยคำสั่ง return หากฟังก์ชันต้องการส่งผลลัพธ์ออกมา หากไม่มีคำสั่ง return ฟังก์ชันจะคืนค่าเป็นอ็อบเจ็กต์ None

eyJsYW5ndWFnZSI6InB5dGhvbiIsInNhbXBsZSI6ImRlZiBoZWxsbygpOlxuICBwcmludChcIkhlbGxvIFdvcmxkXCIpIFxuICByZXR1cm4gIn0=

แน่นอนว่าเมื่อทำไป ฟังก์ชันจะซับซ้อนขึ้น: สามารถเพิ่ม for loop การควบคุมโฟลว์ ฯลฯ เพื่อให้ละเอียดขึ้นได้:

def hello():
    name = input("Enter your name: ")
    if name:
        print(f"Hello {name}")
    else:
        print("Hello World")

hello()

ในฟังก์ชันข้างต้น จะให้ผู้ใช้กรอกชื่อ หากไม่มีการกรอกชื่อ ฟังก์ชันจะพิมพ์ “Hello World” มิฉะนั้น ผู้ใช้จะได้รับคำทักทายแบบระบุชื่อ

โปรดจำไว้ด้วยว่าสามารถกำหนดพารามิเตอร์หนึ่งตัวหรือมากกว่าสำหรับ UDF ได้ จะได้เรียนรู้เพิ่มเติมเมื่อเข้าสู่หัวข้ออาร์กิวเมนต์ของฟังก์ชัน นอกจากนี้ ฟังก์ชันอาจคืนค่าหนึ่งค่าหรือหลายค่าก็ได้

คำสั่ง return

สังเกตว่าเนื่องจากพิมพ์บางอย่างใน UDF hello() อยู่แล้ว จึงไม่จำเป็นต้องคืนค่า จะไม่เห็นความแตกต่างระหว่างฟังก์ชันด้านบนกับฟังก์ชันนี้:

eyJsYW5ndWFnZSI6InB5dGhvbiIsInNhbXBsZSI6ImRlZiBoZWxsb19ub3JldHVybigpOlxuICBwcmludChcIkhlbGxvIFdvcmxkXCIpICJ9

อย่างไรก็ตาม หากต้องการทำงานต่อกับผลลัพธ์ของฟังก์ชันและลองทำโอเปอเรชันกับมัน จะต้องใช้คำสั่ง return เพื่อคืนค่าจริง เช่น สตริง จำนวนเต็ม เป็นต้น พิจารณาสถานการณ์ต่อไปนี้ ซึ่ง hello() คืนค่าสตริง "hello" ในขณะที่ฟังก์ชัน hello_noreturn() คืนค่า None:

eyJsYW5ndWFnZSI6InB5dGhvbiIsInNhbXBsZSI6ImRlZiBoZWxsbygpOlxuICBwcmludChcIkhlbGxvIFdvcmxkXCIpIFxuICByZXR1cm4oXCJoZWxsb1wiKVxuXG5kZWYgaGVsbG9fbm9yZXR1cm4oKTpcbiAgcHJpbnQoXCJIZWxsbyBXb3JsZFwiKVxuICBcbiMgTXVsdGlwbHkgdGhlIG91dHB1dCBvZiBgaGVsbG8oKWAgd2l0aCAyIFxuaGVsbG8oKSAqIDJcblxuIyAoVHJ5IHRvKSBtdWx0aXBseSB0aGUgb3V0cHV0IG9mIGBoZWxsb19ub3JldHVybigpYCB3aXRoIDIgXG5oZWxsb19ub3JldHVybigpICogMiJ9

ฟังก์ชันที่สองจะเกิดข้อผิดพลาดเพราะไม่สามารถทำโอเปอเรชันใด ๆ กับ None ได้ จะได้รับ TypeError ระบุว่าไม่สามารถทำการคูณระหว่าง NoneType (None ที่เป็นผลจาก hello_noreturn()) กับ int (2)

เคล็ดลับ ฟังก์ชันจะออกจากการทำงานทันทีเมื่อพบคำสั่ง return แม้ว่าจะไม่ได้คืนค่าใด ๆ ก็ตาม:

eyJsYW5ndWFnZSI6InB5dGhvbiIsInNhbXBsZSI6ImRlZiBydW4oKTpcbiAgZm9yIHggaW4gcmFuZ2UoMTApOlxuICAgICBpZiB4ID09IDI6XG4gICAgICAgcmV0dXJuXG4gIHByaW50KFwiUnVuIVwiKVxuICBcbnJ1bigpIn0=

อีกประเด็นที่ควรกล่าวถึงเมื่อทำงานกับคำสั่ง return คือสามารถใช้เพื่อคืนค่าหลายค่าได้ โดยทำผ่านทูเพิล

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

ดูตัวอย่างต่อไปนี้เพื่อทำความเข้าใจว่าฟังก์ชันของคุณสามารถคืนค่าหลายค่าได้อย่างไร:

eyJsYW5ndWFnZSI6InB5dGhvbiIsInNhbXBsZSI6IiMgRGVmaW5lIGBwbHVzKClgXG5kZWYgcGx1cyhhLGIpOlxuICBzdW0gPSBhICsgYlxuICByZXR1cm4gKHN1bSwgYSlcblxuIyBDYWxsIGBwbHVzKClgIGFuZCB1bnBhY2sgdmFyaWFibGVzIFxuc3VtLCBhID0gcGx1cygzLDQpXG5cbiMgUHJpbnQgYHN1bSgpYFxucHJpbnQoc3VtKSJ9

หมายเหตุ คำสั่ง return อย่าง return sum, a จะให้ผลเหมือนกับ return (sum, a): แบบแรกจริง ๆ แล้วแพ็ก sum และ a เข้าเป็นทูเพิลเบื้องหลัง!

วิธีเรียกใช้ฟังก์ชัน

ในส่วนก่อนหน้าได้เห็นตัวอย่างมากมายแล้วว่าการเรียกใช้ฟังก์ชันทำอย่างไร การเรียกใช้ฟังก์ชันหมายถึงการรันฟังก์ชันที่นิยามไว้ แล้วแต่จะเรียกตรงจากพรอมต์ Python หรือผ่านฟังก์ชันอื่น (ดังที่จะเห็นในหัวข้อ “Nested Functions”)

เรียกใช้ฟังก์ชัน hello() ที่นิยามใหม่ได้โดยรัน hello() เหมือนในส่วน DataCamp Light ด้านล่างนี้:

eyJsYW5ndWFnZSI6InB5dGhvbiIsInByZV9leGVyY2lzZV9jb2RlIjoiZGVmIGhlbGxvKCk6XG4gIHByaW50KFwiSGVsbG8gV29ybGRcIikgXG4gIHJldHVybiAiLCJzYW1wbGUiOiJoZWxsbygpIn0=

วิธีเพิ่ม docstring ให้ฟังก์ชัน Python

อีกแง่มุมสำคัญของการเขียนฟังก์ชันใน Python: docstring Docstring อธิบายว่าฟังก์ชันทำอะไร เช่น การคำนวณที่ทำหรือค่าที่คืนค่า คำอธิบายนี้ทำหน้าที่เป็นเอกสารของฟังก์ชัน เพื่อให้ผู้ใดก็ตามที่อ่าน docstring ของฟังก์ชันเข้าใจได้ว่าฟังก์ชันทำอะไร โดยไม่ต้องไล่ตามโค้ดทั้งหมดในคำนิยามฟังก์ชัน

Docstring ของฟังก์ชันจะวางไว้บรรทัดถัดจากส่วนหัวของฟังก์ชันและคั่นด้วยเครื่องหมายอัญประกาศสามตัว Docstring ที่เหมาะสมสำหรับฟังก์ชัน hello() คือ ‘พิมพ์ “Hello World”’

def hello() -> None:
    """Prints "Hello World"."""
    print("Hello World")

หมายเหตุ ว่า docstring อาจยาวกว่าตัวอย่างนี้ได้ หากต้องการศึกษา docstring โดยละเอียด แนะนำให้ดูที่คลัง GitHub ของไลบรารี Python เช่น scikit-learn หรือ pandas ซึ่งมีตัวอย่างมากมาย!

Type hints

สิ่งที่เกี่ยวข้องใกล้ชิดกับ docstring และพบเห็นได้บ่อยในโค้ด Python สมัยใหม่คือ type hint ตั้งแต่ Python 3.5 เป็นต้นมา สามารถใส่คำอธิบายชนิดข้อมูลให้กับพารามิเตอร์ของฟังก์ชันและค่าที่คืนว่าจะเป็นชนิดใด ตัวอย่างง่ายที่สุดมีดังนี้:

def plus(a: int, b: int) -> int:
    return a + b

เครื่องหมาย : int หลังแต่ละพารามิเตอร์หมายถึง “ควรเป็นจำนวนเต็ม” และ -> int หลังวงเล็บหมายถึง “ฟังก์ชันนี้คืนค่าเป็นจำนวนเต็ม” Python เองจะไม่บังคับใช้คำอธิบายนี้ขณะรันไทม์ ยังคงส่งสตริงเข้า plus() ได้และ Python จะไม่ร้องจนกว่าจะเกิดปัญหา แต่เครื่องมืออย่าง mypy, pyright และระบบตรวจชนิดในตัวของตัวแก้ไขอย่าง VS Code และ PyCharm จะใช้ hint เหล่านี้เพื่อจับบั๊กก่อนที่จะรันโค้ดจริง

สำหรับชนิดที่ซับซ้อนขึ้น สามารถใช้ generic ที่มีมาให้โดยตรง (ตั้งแต่ Python 3.9+) หรือ import จากโมดูล typing:

def greet(names: list[str]) -> None:
    for name in names:
        print(f"Hello {name}")

def find_user(user_id: int) -> dict | None:
    # returns the user dict, or None if not found
    ...
Type hint เป็นตัวเลือก แต่ถือเป็นแนวปฏิบัติที่ดีสำหรับฟังก์ชันที่ตั้งใจจะนำกลับมาใช้ซ้ำ แบ่งปัน หรือย้อนกลับมาดูในอีกหกเดือนข้างหน้า 它们ทำหน้าที่เป็นเอกสารที่เครื่องตรวจสอบได้ IDE จะเติมคำอัตโนมัติตามนั้น จับการพิมพ์ผิด และเตือนเมื่อส่งชนิดไม่ถูกต้อง

อาร์กิวเมนต์ของฟังก์ชันใน Python

ก่อนหน้านี้ได้เรียนรู้ความแตกต่างระหว่างพารามิเตอร์และอาร์กิวเมนต์โดยย่อแล้ว อาร์กิวเมนต์คือสิ่งที่ส่งให้กับการเรียกใช้ฟังก์ชันหรือเมธอด ขณะที่โค้ดของฟังก์ชันหรือเมธอดจะอ้างถึงอาร์กิวเมนต์ด้วยชื่อพารามิเตอร์ UDF ใน Python รองรับอาร์กิวเมนต์สี่ประเภท:

  • อาร์กิวเมนต์ค่าเริ่มต้น (Default arguments)
  • อาร์กิวเมนต์ที่จำเป็น (Required arguments)
  • อาร์กิวเมนต์แบบระบุคีย์เวิร์ด (Keyword arguments)
  • จำนวนอาร์กิวเมนต์แปรผัน (Variable number of arguments)

Default Arguments

อาร์กิวเมนต์ค่าเริ่มต้นคืออาร์กิวเมนต์ที่รับค่าเริ่มต้นหากไม่มีการส่งค่าเข้ามาระหว่างการเรียกใช้ฟังก์ชัน สามารถกำหนดค่าเริ่มต้นนี้ได้ด้วยโอเปอเรเตอร์กำหนดค่า = ดังตัวอย่างต่อไปนี้:

eyJsYW5ndWFnZSI6InB5dGhvbiIsInNhbXBsZSI6IiMgRGVmaW5lIGBwbHVzKClgIGZ1bmN0aW9uXG5kZWYgcGx1cyhhLGIgPSAyKTpcbiAgcmV0dXJuIGEgKyBiXG4gIFxuIyBDYWxsIGBwbHVzKClgIHdpdGggb25seSBgYWAgcGFyYW1ldGVyXG5wbHVzKGE9MSlcblxuIyBDYWxsIGBwbHVzKClgIHdpdGggYGFgIGFuZCBgYmAgcGFyYW1ldGVyc1xucGx1cyhhPTEsIGI9MykifQ==

Required Arguments

ตามชื่อ อาร์กิวเมนต์ที่จำเป็นของ UDF คือสิ่งที่ต้องมี อาร์กิวเมนต์เหล่านี้ต้องถูกส่งเข้ามาระหว่างการเรียกใช้ฟังก์ชันและต้องอยู่ในลำดับที่ถูกต้อง ดังตัวอย่างต่อไปนี้:

eyJsYW5ndWFnZSI6InB5dGhvbiIsInNhbXBsZSI6IiMgRGVmaW5lIGBwbHVzKClgIHdpdGggcmVxdWlyZWQgYXJndW1lbnRzXG5kZWYgcGx1cyhhLGIpOlxuICByZXR1cm4gYSArIGIifQ==

จำเป็นต้องมีอาร์กิวเมนต์ที่แมปกับพารามิเตอร์ a และ b เพื่อเรียกใช้ฟังก์ชันโดยไม่เกิดข้อผิดพลาด หากสลับ a และ b ผลลัพธ์จะไม่ต่างกัน แต่จะต่างกันได้หากเปลี่ยน plus() เป็นแบบต่อไปนี้:

eyJsYW5ndWFnZSI6InB5dGhvbiIsInNhbXBsZSI6IiMgRGVmaW5lIGBwbHVzKClgIHdpdGggcmVxdWlyZWQgYXJndW1lbnRzXG5kZWYgcGx1cyhhLGIpOlxuICByZXR1cm4gYS9iIn0=

Keyword Arguments

หากต้องการให้แน่ใจว่าเรียกพารามิเตอร์ถูกลำดับ สามารถใช้อาร์กิวเมนต์แบบคีย์เวิร์ดในการเรียกฟังก์ชัน ใช้วิธีนี้เพื่อระบุอาร์กิวเมนต์ด้วยชื่อพารามิเตอร์ มาดูตัวอย่างจากด้านบนเพื่อให้ชัดเจนขึ้น:

eyJsYW5ndWFnZSI6InB5dGhvbiIsInNhbXBsZSI6IiMgRGVmaW5lIGBwbHVzKClgIGZ1bmN0aW9uXG5kZWYgcGx1cyhhLGIpOlxuICByZXR1cm4gYSArIGJcbiAgXG4jIENhbGwgYHBsdXMoKWAgZnVuY3Rpb24gd2l0aCBwYXJhbWV0ZXJzIFxucGx1cygyLDMpXG5cbiMgQ2FsbCBgcGx1cygpYCBmdW5jdGlvbiB3aXRoIGtleXdvcmQgYXJndW1lbnRzXG5wbHVzKGE9MSwgYj0yKSJ9

สังเกตว่าเมื่อใช้อาร์กิวเมนต์แบบคีย์เวิร์ด สามารถสลับลำดับพารามิเตอร์และยังคงได้ผลลัพธ์เดียวกันเมื่อรันฟังก์ชัน:

eyJsYW5ndWFnZSI6InB5dGhvbiIsInNhbXBsZSI6IiMgRGVmaW5lIGBwbHVzKClgIGZ1bmN0aW9uXG5kZWYgcGx1cyhhLGIpOlxuICByZXR1cm4gYSArIGJcbiAgXG4jIENhbGwgYHBsdXMoKWAgZnVuY3Rpb24gd2l0aCBrZXl3b3JkIGFyZ3VtZW50c1xucGx1cyhiPTIsIGE9MSkifQ==

จำนวนอาร์กิวเมนต์แปรผัน

ในกรณีที่ไม่ทราบจำนวนอาร์กิวเมนต์ที่ต้องการส่งให้ฟังก์ชันแน่ชัด สามารถใช้ไวยากรณ์ดังต่อไปนี้กับ *args ได้:

eyJsYW5ndWFnZSI6InB5dGhvbiIsInNhbXBsZSI6IiMgRGVmaW5lIGBwbHVzKClgIGZ1bmN0aW9uIHRvIGFjY2VwdCBhIHZhcmlhYmxlIG51bWJlciBvZiBhcmd1bWVudHNcbmRlZiBwbHVzKCphcmdzKTpcbiAgcmV0dXJuIHN1bShhcmdzKVxuXG4jIENhbGN1bGF0ZSB0aGUgc3VtXG5wbHVzKDEsNCw1KSJ9

เครื่องหมายดอกจัน (*) วางไว้หน้าชื่อตัวแปรที่เก็บค่าของอาร์กิวเมนต์แบบไม่ใช่คีย์เวิร์ดทั้งหมด สังเกตว่าสามารถใช้ชื่ออื่นแทน *args เช่น *varint, *var_int_args หรือชื่อใด ๆ เมื่อส่งเข้าไปยังฟังก์ชัน plus() ก็ได้

เคล็ดลับ: ลองแทนที่ *args ด้วยชื่ออื่นที่มีดอกจัน จะเห็นว่าโค้ดด้านบนยังทำงานต่อไปได้!

จะเห็นว่าฟังก์ชันด้านบนใช้ฟังก์ชันที่มีมาให้ของ Python อย่าง sum() เพื่อบวกรวมอาร์กิวเมนต์ทั้งหมดที่ส่งเข้าไปยัง plus() 

ตัวแปรแบบ global กับแบบ local

โดยทั่วไป ตัวแปรที่กำหนดในเนื้อฟังก์ชันจะมีขอบเขตแบบ local ส่วนตัวแปรที่กำหนดไว้ภายนอกจะมีขอบเขตแบบ global นั่นหมายความว่า ตัวแปร local ถูกกำหนดภายในบล็อกของฟังก์ชันและเข้าถึงได้เฉพาะภายในฟังก์ชันนั้น ขณะที่ตัวแปร global สามารถเข้าถึงได้โดยฟังก์ชันทั้งหมดในสคริปต์ของคุณ:

eyJsYW5ndWFnZSI6InB5dGhvbiIsInNhbXBsZSI6IiMgR2xvYmFsIHZhcmlhYmxlIGBpbml0YFxuaW5pdCA9IDFcblxuIyBEZWZpbmUgYHBsdXMoKWAgZnVuY3Rpb24gdG8gYWNjZXB0IGEgdmFyaWFibGUgbnVtYmVyIG9mIGFyZ3VtZW50c1xuZGVmIHBsdXMoKmFyZ3MpOlxuICAjIExvY2FsIHZhcmlhYmxlIGBzdW0oKWBcbiAgdG90YWwgPSAwXG4gIGZvciBpIG4gYXJnczoXG4gICAgdG90YWwgKz0gaVxuICByZXR1cm4gdG90YWxcbiAgXG4jIEFjY2VzcyB0aGUgZ2xvYmFsIHZhcmlhYmxlXG5wcmludChcInRoaXMgaXMgdGhlIGluaXRpYWxpemVkIHZhbHVlIFwiICsgc3RyKGluaXQpKVxuXG4jIChUcnkgdG8pIGFjY2VzcyB0aGUgbG9jYWwgdmFyaWFibGVcbnByaW50KFwidGhpcyBpcyB0aGUgc3VtIFwiICsgc3RyKHRvdGFsKSkifQ==

จะเห็นว่าเกิด NameError ระบุว่า name 'total' is not defined เมื่อพยายามพิมพ์ตัวแปร local total ที่ถูกกำหนดภายในเนื้อฟังก์ชัน ด้านทางกลับกัน ตัวแปร init สามารถพิมพ์ได้โดยไม่มีปัญหา

พารามิเตอร์แบบ positional-only และ keyword-only

ตั้งแต่ Python 3.8 เป็นต้นมา สามารถควบคุมวิธีการส่งอาร์กิวเมนต์ได้มากขึ้นด้วยเครื่องหมายพิเศษสองตัวในลายเซ็นของฟังก์ชัน คือ / และ * สิ่งที่อยู่ก่อน / จะส่งได้เฉพาะแบบตำแหน่งเท่านั้น ส่วนที่อยู่หลัง * จะส่งได้เฉพาะแบบคีย์เวิร์ดเท่านั้น

def greet(name, /, greeting="Hello", *, punctuation="!"):
    print(f"{greeting} {name}{punctuation}")

 ตัวอย่างการเรียกใช้จะเป็นดังนี้:

greet("Alice")                          # works
greet("Alice", greeting="Hi")           # works
greet("Alice", "Hi", punctuation="?")   # works

greet(name="Alice")                     # TypeError: name is positional-only
greet("Alice", "Hi", "?")               # TypeError: punctuation is keyword-only

ทำไมถึงอยากใช้แบบนี้? มีสองเหตุผลหลัก

หนึ่ง, พารามิเตอร์แบบ positional-only ช่วยให้เปลี่ยนชื่อในภายหลังได้โดยไม่ทำให้โค้ดของใครพัง เพราะไม่มีใครได้รับอนุญาตให้ใช้ชื่อนั้นเป็นคีย์เวิร์ด จึงเปลี่ยนชื่อได้อิสระ

สอง, พารามิเตอร์แบบ keyword-only บังคับให้ผู้เรียกใช้ระบุอย่างชัดเจนว่ากำลังส่งอะไร ทำให้การเรียกอ่านง่ายขึ้นเมื่อมีแฟลกหรือการตั้งค่าทางเลือกหลายตัว

สรุปคือ เป็นวิธีที่สะอาดในการบังคับใช้เจตนา

ฟังก์ชันนิรนามใน Python

ฟังก์ชันนิรนามใน Python เรียกว่าฟังก์ชันแลมบ์ดา เพราะแทนที่จะประกาศด้วยคีย์เวิร์ดมาตรฐาน def จะใช้คีย์เวิร์ด lambda

eyJsYW5ndWFnZSI6InB5dGhvbiIsInNhbXBsZSI6ImRvdWJsZSA9IGxhbWJkYSB4OiB4KjJcblxuZG91YmxlKDUpIn0=

ในส่วน DataCamp Light ด้านบน lambda x: x*2 คือฟังก์ชันนิรนามหรือฟังก์ชันแลมบ์ดา x คืออาร์กิวเมนต์ และ x*2 คือ expression หรือคำสั่งที่ถูกประเมินและคืนค่า ความพิเศษของฟังก์ชันนี้คือไม่มีชื่อ แตกต่างจากตัวอย่างในส่วนแรกของบทช่วยสอนฟังก์ชัน หากต้องเขียนฟังก์ชันข้างต้นเป็น UDF จะได้ผลลัพธ์ดังนี้:

def double(x):
  return x*2

พิจารณาตัวอย่างฟังก์ชันแลมบ์ดาที่ทำงานกับอาร์กิวเมนต์สองตัว:

eyJsYW5ndWFnZSI6InB5dGhvbiIsInNhbXBsZSI6IiMgYHN1bSgpYCBsYW1iZGEgZnVuY3Rpb25cbnN1bSA9IGxhbWJkYSB4LCB5OiB4ICsgeTtcblxuIyBDYWxsIHRoZSBgc3VtKClgIGFub255bW91cyBmdW5jdGlvblxuc3VtKDQsNSlcblxuIyBcIlRyYW5zbGF0ZVwiIHRvIGEgVURGXG5kZWYgc3VtKHgsIHkpOlxuICByZXR1cm4geCt5In0=

มักใช้ฟังก์ชันนิรนามเมื่อจำเป็นต้องใช้ฟังก์ชันที่ไม่มีชื่อชั่วคราวและถูกสร้างขึ้นขณะรันไทม์ บริบทที่เกี่ยวข้องเช่นเมื่อทำงานกับ filter(), map() และ reduce():

eyJsYW5ndWFnZSI6InB5dGhvbiIsInNhbXBsZSI6ImZyb20gZnVuY3Rvb2xzIGltcG9ydCByZWR1Y2VcblxubXlfbGlzdCA9IFsxLDIsMyw0LDUsNiw3LDgsOSwxMF1cblxuIyBVc2UgbGFtYmRhIGZ1bmN0aW9uIHdpdGggYGZpbHRlcigpYFxuZmlsdGVyZWRfbGlzdCA9IGxpc3QoZmlsdGVyKGxhbWJkYSB4OiAoeCoyID4gMTApLCBteV9saXN0KSlcblxuIyBVc2UgbGFtYmRhIGZ1bmN0aW9uIHdpdGggYG1hcCgpYFxubWFwcGVkX2xpc3QgPSBsaXN0KG1hcChsYW1iZGEgeDogeCoyLCBteV9saXN0KSlcblxuIyBVc2UgbGFtYmRhIGZ1bmN0aW9uIHdpdGggYHJlZHVjZSgpYFxucmVkdWNlZF9saXN0ID0gcmVkdWNlKGxhbWJkYSB4LCB5OiB4K3ksIG15X2xpc3QpXG5cbnByaW50KGZpbHRlcmVkX2xpc3QpXG5wcmludChtYXBwZWRfbGlzdClcbnByaW50KHJlZHVjZWRfbGlzdCkifQ==

ฟังก์ชัน filter() จะกรองลิสต์อินพุตเดิม my_list ตามเงื่อนไข >10 ตามชื่อของมัน ส่วน map() จะนำฟังก์ชันไปใช้กับทุกองค์ประกอบของลิสต์ my_list ในที่นี้คือคูณทุกองค์ประกอบด้วย 2

สังเกตว่า reduce() อยู่ในไลบรารี functools ใช้ฟังก์ชันนี้แบบสะสมกับรายการในลิสต์ my_list จากซ้ายไปขวา และย่อลำดับให้เหลือค่าเดียว ซึ่งในที่นี้คือ 55

การใช้ main() เป็นฟังก์ชันใน Python

หากมีประสบการณ์กับภาษาอื่นอย่าง Java จะทราบว่าต้องมีฟังก์ชัน main เพื่อรันฟังก์ชันต่าง ๆ แต่จากตัวอย่างด้านบนจะเห็นว่า Python ไม่จำเป็นต้องมี อย่างไรก็ตาม การใส่ฟังก์ชัน main() ในโปรแกรม Python จะช่วยจัดโครงร่างโค้ดอย่างมีเหตุผล องค์ประกอบที่สำคัญที่สุดจะถูกรวมไว้ในฟังก์ชัน main() นี้

สามารถนิยามฟังก์ชัน main() และเรียกใช้ได้ง่าย ๆ เช่นเดียวกับฟังก์ชันอื่น ๆ ด้านบน:

eyJsYW5ndWFnZSI6InB5dGhvbiIsInByZV9leGVyY2lzZV9jb2RlIjoiZGVmIGhlbGxvKCk6XG4gIHByaW50KFwiSGVsbG8gV29ybGRcIikgXG4gIHJldHVybiAiLCJzYW1wbGUiOiIjIERlZmluZSBgbWFpbigpYCBmdW5jdGlvblxuZGVmIG1haW4oKTpcbiAgaGVsbG8oKVxuICBwcmludChcIlRoaXMgaXMgYSBtYWluIGZ1bmN0aW9uXCIpXG5cbm1haW4oKSJ9

อย่างไรก็ตาม ในสภาพนี้ โค้ดของฟังก์ชัน main() จะถูกเรียกเมื่อมีการ import ไฟล์เป็นโมดูล เพื่อป้องกันไม่ให้เกิดขึ้น ควรเรียกฟังก์ชัน main() เมื่อ __name__ == '__main__'

ดังนั้นโค้ดในส่วนด้านบนจะกลายเป็นดังนี้:

eyJsYW5ndWFnZSI6InB5dGhvbiIsInByZV9leGVyY2lzZV9jb2RlIjoiZGVmIGhlbGxvKCk6XG4gIHByaW50KFwiSGVsbG8gV29ybGRcIikgXG4gIHJldHVybiAiLCJzYW1wbGUiOiIjIERlZmluZSBgbWFpbigpYCBmdW5jdGlvblxuZGVmIG1haW4oKTpcbiAgaGVsbG8oKVxuICBwcmludChcIlRoaXMgaXMgYSBtYWluIGZ1bmN0aW9uXCIpXG4gIFxuIyBFeGVjdXRlIGBtYWluKClgIGZ1bmN0aW9uIFxuaWYgX19uYW1lX18gPT0gJ19fbWFpbl9fJzpcbiAgICBtYWluKCkifQ==

หมายเหตุ นอกเหนือจากฟังก์ชัน __main__ แล้ว ยังมีฟังก์ชัน __init__ ที่ใช้เริ่มต้นอินสแตนซ์ของคลาสหรืออ็อบเจ็กต์ กล่าวโดยย่อคือทำหน้าที่เป็นคอนสตรักเตอร์หรือตัวเริ่มต้น และถูกเรียกอัตโนมัติเมื่อสร้างอินสแตนซ์ของคลาสใหม่ ด้วยฟังก์ชันนี้ อ็อบเจ็กต์ที่สร้างใหม่จะถูกกำหนดให้กับพารามิเตอร์ self ซึ่งเห็นไปแล้วในบทช่วยสอนนี้ ดูตัวอย่างต่อไปนี้:

class Dog:
    """A simple Dog class.

    Args:
        legs: Number of legs so that the dog can walk.
        color: The color of the fur.
    """

    def __init__(self, legs: int, color: str) -> None:
        self.legs = legs
        self.color = color

    def bark(self) -> str:
        return "bark" * 2

if __name__ == "__main__":
    dog = Dog(4, "brown")
    print(dog.bark())

ฝึกฟังก์ชัน Python ต่อให้คล่อง

ยินดีด้วย! ผ่านบทช่วยสั้น ๆ เกี่ยวกับฟังก์ชันใน Python แล้ว หากต้องการทบทวนเนื้อหา Python พื้นฐานอื่น ๆ อย่าพลาดคอร์ส Data Types for Data Science ซึ่งจะช่วยย้ำและฝึกความรู้เกี่ยวกับลิสต์, ดิกชันนารี, ทูเพิล, เซต และวันที่และเวลา

คำถามที่พบบ่อยเกี่ยวกับฟังก์ชันใน Python

ฟังก์ชันใน Python คืออะไร?

ฟังก์ชันคือบล็อกโค้ดที่นำกลับมาใช้ซ้ำได้เพื่อทำงานเฉพาะอย่าง สามารถรับอินพุต ประมวลผล และคืนเอาต์พุตได้

กำหนดฟังก์ชันใน Python อย่างไร?

เพื่อกำหนดฟังก์ชันใน Python ให้ใช้คีย์เวิร์ด def ตั้งชื่อฟังก์ชัน ใส่พารามิเตอร์ (ถ้ามี) ในวงเล็บ เขียนโค้ด แล้วอาจใช้ return เพื่อคืนค่า

ความแตกต่างระหว่างฟังก์ชันกับเมธอดใน Python คืออะไร?

ฟังก์ชันอยู่เดี่ยว ๆ แต่เมธอดเป็นส่วนหนึ่งของคลาส เมธอดทั้งหมดคือฟังก์ชัน แต่ไม่ใช่ทุกฟังก์ชันคือเมธอด

ประเภทของฟังก์ชันใน Python มีอะไรบ้าง?

Python มีฟังก์ชันที่มีมาให้ (เช่น print()) ฟังก์ชันที่ผู้ใช้กำหนดเอง (ที่คุณสร้างขึ้น) และฟังก์ชันนิรนาม (ฟังก์ชัน lambda ชั่วคราว)

ความแตกต่างระหว่างพารามิเตอร์และอาร์กิวเมนต์คืออะไร?

พารามิเตอร์คือช่องว่างรองรับในคำจำกัดความของฟังก์ชัน ส่วนอาร์กิวเมนต์คือค่าจริงที่ส่งเข้าไปเมื่อเรียกใช้ฟังก์ชัน

ฟังก์ชันแลมบ์ดาคืออะไร?

ฟังก์ชันแลมบ์ดาคือฟังก์ชันไม่มีชื่อแบบบรรทัดเดียวสำหรับงานรวดเร็ว

ทำไมต้องใช้ฟังก์ชัน __main__?

ฟังก์ชัน __main__ ช่วยจัดโค้ดให้เป็นระเบียบและทำให้ส่วนที่ระบุรันเฉพาะเมื่อสคริปต์ถูกรันโดยตรง ไม่ใช่เมื่อถูก import

ความแตกต่างระหว่างตัวแปร global และ local คืออะไร?

ตัวแปรแบบ global ใช้ได้ทุกที่ ส่วนตัวแปรแบบ local ใช้ได้เฉพาะภายในฟังก์ชันของมันเท่านั้น

หัวข้อ

เรียนรู้เพิ่มเติมเกี่ยวกับ Python

Courses

Introduction to Python

4 ชม.
6.8M
Master the basics of data analysis with Python in just four hours. This online course will introduce the Python interface and explore popular packages.
ดูรายละเอียดCodestin Search App
เริ่มหลักสูตร
ดูเพิ่มเติมCodestin Search App