Notes & software courses · Free to learn
Aph's Blog
On this page

วันที่ 14 — Higher Order Functions

👋 อ่านฟรีทั้งหมดบน Aph's Blog — เนื้อหาภาษาไทย ทำตามทีละหน้าใน sidebar ได้เลย หากมีข้อเสนอแนะหรืออยากให้เพิ่มหัวข้อไหน บอกได้เสมอ

เรียนรู้ Higher Order Functions, Closures, Decorators และ Built-in functions อย่าง map, filter และ reduce ใน Python

Higher Order Functions

ใน Python functions ถูกมองว่าเป็น first class citizens ทำให้ทำสิ่งเหล่านี้ได้:

  • Function สามารถรับ functions อื่นเป็น parameters ได้
  • Function สามารถ return function เป็นผลลัพธ์ได้
  • Function สามารถแก้ไขได้
  • Function สามารถกำหนดให้กับตัวแปรได้

ในส่วนนี้จะเรียน: การจัดการ functions เป็น parameters, การ return functions จาก functions อื่น และการใช้ Python closures กับ decorators

Function เป็น Parameter

python
def sum_numbers(nums):  # normal function
    return sum(nums)    # a sad function abusing the built-in sum function :<

def higher_order_function(f, lst):  # function as a parameter
    summation = f(lst)
    return summation
result = higher_order_function(sum_numbers, [1, 2, 3, 4, 5])
print(result)       # 15

Function เป็น Return Value

python
def square(x):          # a square function
    return x ** 2

def cube(x):            # a cube function
    return x ** 3

def absolute(x):        # an absolute value function
    if x >= 0:
        return x
    else:
        return -(x)

def higher_order_function(type): # a higher order function returning a function
    if type == 'square':
        return square
    elif type == 'cube':
        return cube
    elif type == 'absolute':
        return absolute

result = higher_order_function('square')
print(result(3))       # 9
result = higher_order_function('cube')
print(result(3))       # 27
result = higher_order_function('absolute')
print(result(-3))      # 3

Python Closures

Python อนุญาตให้ nested function เข้าถึง outer scope ของ enclosing function ซึ่งเรียกว่า Closure Closure สร้างได้โดยการซ้อน function ไว้ใน function อื่นแล้ว return inner function:

python
def add_ten():
    ten = 10
    def add(num):
        return num + ten
    return add

closure_result = add_ten()
print(closure_result(5))  # 15
print(closure_result(10))  # 20

Python Decorators

Decorator คือ design pattern ใน Python ที่ให้ผู้ใช้เพิ่มความสามารถใหม่ให้กับ object ที่มีอยู่โดยไม่ต้องแก้ไขโครงสร้างเดิม Decorators มักจะถูกเรียกก่อน definition ของ function ที่ต้องการ decorate

การสร้าง Decorators

ในการสร้าง decorator function เราต้องมี outer function ที่มี inner wrapper function:

python
# Normal function
def greeting():
    return 'Welcome to Python'
def uppercase_decorator(function):
    def wrapper():
        func = function()
        make_uppercase = func.upper()
        return make_uppercase
    return wrapper
g = uppercase_decorator(greeting)
print(g())          # WELCOME TO PYTHON

## Let us implement the example above with a decorator

def uppercase_decorator(function):
    def wrapper():
        func = function()
        make_uppercase = func.upper()
        return make_uppercase
    return wrapper
@uppercase_decorator
def greeting():
    return 'Welcome to Python'
print(greeting())   # WELCOME TO PYTHON

การใช้ Decorators หลายตัวกับ Function เดียว

python
# First Decorator
def uppercase_decorator(function):
    def wrapper():
        func = function()
        make_uppercase = func.upper()
        return make_uppercase
    return wrapper

# Second decorator
def split_string_decorator(function):
    def wrapper():
        func = function()
        splitted_string = func.split()
        return splitted_string
    return wrapper

#Decorators will be executed from bottom to top
@split_string_decorator
@uppercase_decorator     # order with decorators is important in this case - .upper() function does not work with lists
def greeting():
    return 'Welcome to Python'
print(greeting())   # ['WELCOME', 'TO', 'PYTHON']

การรับ Parameters ใน Decorator Functions

python
def decorator_with_parameters(function):
    def wrapper_accepting_parameters(para1, para2, para3):
        function(para1, para2, para3)
        print("I live in {}".format(para3))
    return wrapper_accepting_parameters

@decorator_with_parameters
def print_full_name(first_name, last_name, country):
    print("I am {} {}. I love to teach.".format(
        first_name, last_name))

print_full_name("Asabeneh", "Yetayeh",'Finland')

Built-in Higher Order Functions

Built-in higher order functions ที่จะเรียนคือ map(), filter และ reduce Lambda function สามารถส่งเป็น parameter ได้และเหมาะมากกับ functions เหล่านี้

Python — Map Function

map() function รับ function และ iterable เป็น parameters:

python
    # syntax
    map(function, iterable)

ตัวอย่างที่ 1:

python
numbers = [1, 2, 3, 4, 5] # iterable
def square(x):
    return x ** 2
numbers_squared = map(square, numbers)
print(list(numbers_squared))    # [1, 4, 9, 16, 25]
# Lets apply it with a lambda function
numbers_squared = map(lambda x : x ** 2, numbers)
print(list(numbers_squared))    # [1, 4, 9, 16, 25]

ตัวอย่างที่ 2:

python
numbers_str = ['1', '2', '3', '4', '5']  # iterable
numbers_int = map(int, numbers_str)
print(list(numbers_int))    # [1, 2, 3, 4, 5]

ตัวอย่างที่ 3:

python
names = ['Asabeneh', 'Lidiya', 'Ermias', 'Abraham']  # iterable

def change_to_upper(name):
    return name.upper()

names_upper_cased = map(change_to_upper, names)
print(list(names_upper_cased))    # ['ASABENEH', 'LIDIYA', 'ERMIAS', 'ABRAHAM']

# Let us apply it with a lambda function
names_upper_cased = map(lambda name: name.upper(), names)
print(list(names_upper_cased))    # ['ASABENEH', 'LIDIYA', 'ERMIAS', 'ABRAHAM']

Python — Filter Function

filter() function เรียก function ที่กำหนดซึ่ง return boolean สำหรับแต่ละ item ใน iterable และกรอง items ที่ผ่านเงื่อนไขออกมา:

python
    # syntax
    filter(function, iterable)

ตัวอย่างที่ 1:

python
# Lets filter only even nubers
numbers = [1, 2, 3, 4, 5]  # iterable

def is_even(num):
    if num % 2 == 0:
        return True
    return False

even_numbers = filter(is_even, numbers)
print(list(even_numbers))       # [2, 4]

ตัวอย่างที่ 2:

python
numbers = [1, 2, 3, 4, 5]  # iterable

def is_odd(num):
    if num % 2 != 0:
        return True
    return False

odd_numbers = filter(is_odd, numbers)
print(list(odd_numbers))       # [1, 3, 5]
python
# Filter long name
names = ['Asabeneh', 'Lidiya', 'Ermias', 'Abraham']  # iterable
def is_name_long(name):
    if len(name) > 7:
        return True
    return False

long_names = filter(is_name_long, names)
print(list(long_names))         # ['Asabeneh']

Python — Reduce Function

reduce() function ถูก define ใน functools module ต้อง import จาก module นี้ รับ function และ iterable เป็น parameters แต่ return ค่าเดียวแทน iterable:

python
from functools import reduce

numbers_str = ['1', '2', '3', '4', '5']  # iterable
def add_two_nums(x, y):
    return int(x) + int(y)

total = reduce(add_two_nums, numbers_str)
print(total)    # 15

💻 แบบฝึกหัด — วันที่ 14

python
countries = ['Estonia', 'Finland', 'Sweden', 'Denmark', 'Norway', 'Iceland']
names = ['Asabeneh', 'Lidiya', 'Ermias', 'Abraham']
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

ระดับ 1

  1. อธิบายความแตกต่างระหว่าง map, filter และ reduce
  2. อธิบายความแตกต่างระหว่าง higher order function, closure และ decorator
  3. กำหนด call function ก่อน map, filter หรือ reduce ดูตัวอย่าง
  4. ใช้ for loop print แต่ละประเทศใน countries list
  5. ใช้ for loop print แต่ละชื่อใน names list
  6. ใช้ for loop print แต่ละตัวเลขใน numbers list

ระดับ 2

  1. ใช้ map สร้าง list ใหม่โดยเปลี่ยนแต่ละประเทศเป็นตัวพิมพ์ใหญ่ใน countries list
  2. ใช้ map สร้าง list ใหม่โดยเปลี่ยนแต่ละตัวเลขเป็น square ใน numbers list
  3. ใช้ map เปลี่ยนแต่ละชื่อเป็นตัวพิมพ์ใหญ่ใน names list
  4. ใช้ filter กรองประเทศที่มีคำว่า 'land' ออกมา
  5. ใช้ filter กรองประเทศที่มีตัวอักษรพอดี 6 ตัว
  6. ใช้ filter กรองประเทศที่มีตัวอักษร 6 ตัวขึ้นไปจาก country list
  7. ใช้ filter กรองประเทศที่ขึ้นต้นด้วย 'E'
  8. เชื่อมต่อ list iterators สองตัวขึ้นไป เช่น arr.map(callback).filter(callback).reduce(callback)
  9. ประกาศ function ชื่อ get_string_lists รับ list เป็น parameter แล้ว return list ที่มีแค่ string items
  10. ใช้ reduce รวมตัวเลขทั้งหมดใน numbers list
  11. ใช้ reduce ต่อชื่อประเทศทั้งหมดและสร้างประโยค: Estonia, Finland, Sweden, Denmark, Norway, and Iceland are north European countries
  12. ประกาศ function ชื่อ categorize_countries ที่ return list ของประเทศที่มี pattern บางอย่าง (เช่น 'land', 'ia', 'island', 'stan')
  13. สร้าง function ที่ return dictionary โดย keys คือตัวอักษรแรกของประเทศ และ values คือจำนวนประเทศที่ขึ้นต้นด้วยตัวอักษรนั้น
  14. ประกาศ function get_first_ten_countries — return list ของ 10 ประเทศแรกจาก countries list ใน data folder
  15. ประกาศ function get_last_ten_countries ที่ return 10 ประเทศสุดท้ายใน countries list

ระดับ 3

  1. ใช้ไฟล์ countries_data.py แล้วทำ tasks ต่อไปนี้:
    - Sort ประเทศตามชื่อ, ตามเมืองหลวง, ตามประชากร
    - Sort 10 ภาษาที่มีคนพูดมากที่สุดตาม location
    - Sort 10 ประเทศที่มีประชากรมากที่สุด