0Pricing
Coding Interview Prep · บทเรียน

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

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

ฟังก์ชัน คลอเชอร์ และแลมบ์ดา เป็นบทเรียน Coding Interview Prep ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Coding Interview Prep และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Coding Interview Prep มีบทเรียนทั้งหมด 4 บทเรียน

การกำหนดฟังก์ชันใน Python

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

def is_palindrome(s: str) -> bool:
    '''Return True if s reads the same forwards and backwards.'''
    s = s.lower()
    return s == s[::-1]

print(is_palindrome('Racecar'))  # True
print(is_palindrome('hello'))    # False

# Functions as values
checks = [is_palindrome]
print(checks[0]('level'))  # True

อาร์กิวเมนต์ค่าเริ่มต้นและอาร์กิวเมนต์แบบคีย์เวิร์ด

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

# WRONG: shared mutable default
def bad_append(val, lst=[]):
    lst.append(val)
    return lst

print(bad_append(1))  # [1]
print(bad_append(2))  # [1, 2]  surprise!

# CORRECT: use None sentinel
def good_append(val, lst=None):
    if lst is None:
        lst = []
    lst.append(val)
    return lst

print(good_append(1))  # [1]
print(good_append(2))  # [2]

*args และ **kwargs

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

def total(*args):
    return sum(args)

print(total(1, 2, 3))     # 6
print(total(1, 2, 3, 4))  # 10

# Unpack a list as positional args
point = [3, 7]
print(max(*point))   # 7

# **kwargs
def greet(**kwargs):
    name = kwargs.get('name', 'World')
    return f'Hello, {name}!'

print(greet(name='Alice'))  # Hello, Alice!

นิพจน์แลมบ์ดา

lambda คือฟังก์ชันขนาดเล็กที่เขียนในบรรทัดเดียว: lambda params: expression เหมาะอย่างยิ่งสำหรับใช้เป็นคีย์แบบรวดเร็วใน sorted หรือ max หากโค้ดซับซ้อนกว่านั้น การใช้ def ที่มีชื่อจะอ่านเข้าใจง่ายกว่า

# Lambda as sort key
pairs = [(1, 3), (2, 1), (3, 2)]
sorted_by_second = sorted(pairs, key=lambda p: p[1])
print(sorted_by_second)  # [(2,1),(3,2),(1,3)]

# Lambda with map
double = list(map(lambda n: n * 2, [1, 2, 3]))
print(double)  # [2, 4, 6]

# Named function is clearer for complex logic
def sort_key(p):
    return (p[1], -p[0])  # secondary sort
print(sorted(pairs, key=sort_key))

ฟังก์ชันซ้อนกันและคลอเชอร์

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

def make_counter(start=0):
    count = [start]  # list to allow mutation
    def increment():
        count[0] += 1
        return count[0]
    return increment

counter = make_counter()
print(counter())  # 1
print(counter())  # 2

# Alternative: nonlocal keyword
def make_counter2():
    count = 0
    def increment():
        nonlocal count
        count += 1
        return count
    return increment

คลอเชอร์ใน DFS แบบเรียกซ้ำ

รูปแบบที่ใช้บ่อยคือกำหนดฟังก์ชันช่วย dfs ไว้ภายในฟังก์ชันหลัก แล้วให้ฟังก์ชันช่วยรวบรวมผลลัพธ์ลงในตัวแปรภายนอก ฟังก์ชันด้านในจึงเป็นคลอเชอร์ที่ครอบคลุมขอบเขตนั้น

def max_depth(root):
    '''Closure pattern for tree DFS.'''
    max_d = [0]  # mutable container for closure

    def dfs(node, depth):
        if node is None:
            return
        max_d[0] = max(max_d[0], depth)
        dfs(node.left, depth + 1)
        dfs(node.right, depth + 1)

    dfs(root, 1)
    return max_d[0]
# This pattern avoids a class or global state.

functools.lru_cache สำหรับการจดจำผลลัพธ์

lru_cache (หรือ @cache ในรุ่น 3.9 ขึ้นไป) จะจดจำผลลัพธ์ของฟังก์ชันตามอาร์กิวเมนต์ ทำให้ฟังก์ชันฟีโบนัชชีนาอีฟเปลี่ยนจาก O(2^n) เป็น O(n) อาร์กิวเมนต์ต้องแฮชได้ ดังนั้นควรใช้ทูเพิล

from functools import lru_cache

@lru_cache(maxsize=None)
def fib(n):
    if n <= 1:
        return n
    return fib(n - 1) + fib(n - 2)

print(fib(40))   # 102334155  fast!
print(fib.cache_info())  # hits, misses, size

ฟังก์ชันระดับสูง

ฟังก์ชันระดับสูง คือฟังก์ชันที่รับหรือคืนค่าฟังก์ชัน sorted, map และ filter ล้วนจัดอยู่ในประเภทนี้ การเขียนฟังก์ชันของคุณเองช่วยแยกรูปแบบการทำงานที่ซ้ำกันออกมาเป็นนามธรรม โค้ดจะแสดงการประกอบฟังก์ชัน

def apply_twice(f, x):
    return f(f(x))

print(apply_twice(lambda n: n * 2, 3))  # 12  (3*2*2)

# Composing transformations
def compose(f, g):
    return lambda x: f(g(x))

double = lambda n: n * 2
add_one = lambda n: n + 1
double_then_add = compose(add_one, double)
print(double_then_add(5))  # 11  ((5*2)+1)

การเรียกซ้ำด้วยฟังก์ชันช่วย

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

def flatten(nested):
    '''Flatten an arbitrarily nested list.'''
    result = []

    def _flatten(lst):
        for item in lst:
            if isinstance(item, list):
                _flatten(item)
            else:
                result.append(item)

    _flatten(nested)
    return result

print(flatten([1, [2, [3, 4], 5], 6]))
# [1, 2, 3, 4, 5, 6]

ฟังก์ชันบางส่วนด้วย functools.partial

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

from functools import partial

def power(base, exp):
    return base ** exp

square = partial(power, exp=2)
cube   = partial(power, exp=3)

print(square(5))   # 25
print(cube(3))     # 27
print(list(map(square, [1, 2, 3, 4])))  # [1, 4, 9, 16]

แลมบ์ดาสำหรับตัวเปรียบเทียบแบบกำหนดเอง

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

from functools import cmp_to_key

def largest_number(nums):
    def compare(a, b):
        if a + b > b + a: return -1
        if a + b < b + a: return 1
        return 0
    strs = list(map(str, nums))
    strs.sort(key=cmp_to_key(compare))
    result = ''.join(strs)
    return '0' if result[0] == '0' else result

print(largest_number([3, 30, 34, 5, 9]))  # '9534330'

ตรวจสอบความเข้าใจอย่างรวดเร็ว

ตรวจสอบความเข้าใจอย่างรวดเร็ว — ถึงเวลาทดสอบสิ่งที่คุณเรียนรู้เกี่ยวกับฟังก์ชัน คลอเชอร์ และแลมบ์ดา สูดหายใจแล้วเริ่มได้เลย 🚀

ทบทวนบทเรียน

สรุป: ห้ามใช้ค่าเริ่มต้นที่เปลี่ยนแปลงได้ (ให้ใช้ None) คลอเชอร์ ช่วยให้ฟังก์ชันช่วยด้านในเข้าถึงตัวแปรด้านนอกสำหรับ DFS และเครื่องมือใน functools เช่น lru_cache ช่วยสร้างโซลูชันที่ทำงานได้รวดเร็ว

คำถามที่พบบ่อย

บทเรียน “ฟังก์ชัน คลอเชอร์ และแลมบ์ดา” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “ฟังก์ชัน คลอเชอร์ และแลมบ์ดา” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Coding Interview Prep ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Coding Interview Prep มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “ฟังก์ชัน คลอเชอร์ และแลมบ์ดา”

กำหนดฟังก์ชันช่วยที่นำกลับมาใช้ซ้ำได้ ใช้อาร์กิวเมนต์เริ่มต้น และประยุกต์นิพจน์แลมบ์ดากับการเรียงลำดับและรูปแบบเชิงฟังก์ชันในโจทย์สัมภาษณ์ คุณปฏิบัติ Coding Interview Prep ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Coding Interview Prep หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Coding Interview Prep บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน

บทเรียน “ฟังก์ชัน คลอเชอร์ และแลมบ์ดา” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Coding Interview Prep นี้ได้ไหม

ได้ บทเรียน Coding Interview Prep ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. ลิสต์ ทูเพิล และการตัดแบ่ง
  2. ดิกชันนารีและเซตใน Python
  3. การสร้างข้อมูลแบบย่อและฟังก์ชันในตัว
  4. ฟังก์ชัน คลอเชอร์ และแลมบ์ดา
← กลับไปที่ Coding Interview Prep