---
# System prepended metadata

title: Virgil - Practice Python - S61 Function
tags: [' LearnWorld', ' PracticePython', Virgil]

---

---
title: Virgil - Practice Python - S61 Function
tags: Virgil, LearnWorld, PracticePython
---

# Function

Function trong Python hay trong lập trình là một **khái niệm cốt lõi** rất quan trọng. Function cho phép chúng ta:

- Đóng gói các logic để tái sử dụng nhiều lần
- Chia nhỏ vấn đề và thiết kế cấu trúc hệ thống
- Thực hiện một vài thuật toán phức tạp, ví dụ như đệ quy (recursive function)

Chúng ta sẽ xem cách định nghĩa function thông qua ví dụ sau:

Viết một function có 3 tham số là dạng số và trả về khoảng cách nhỏ nhất giữa hai số trong ba số đó. Ví dụ khoảng cách nhỏ nhất giữa `1, 3, 7` là `2` (khoảng cách giữa `1` và `3`).

```python
def least_difference(a, b, c):
    diff1 = abs(a - b)
    diff2 = abs(b - c)
    diff3 = abs(a - c)

    return min(diff1, diff2, diff3)

# Call the function
print(least_difference(1, 3, 7))
```

Một số điểm lưu ý:

- `a, b, c` gọi là tham số đầu vào (**arguments**). Khi gọi function, bạn phải truyền giá trị cho arguments để function có thể tính toán.
- `abs()`, `min()`, `print()` gọi là các built-in function, là những function có sẵn của Python mà bạn có thể sử dụng.
- Câu lệnh `return` khi được thực thi sẽ kết thúc function, mọi câu lệnh phía sau return sẽ không được gọi.
- `return` không phải là bắt buộc trong định nghĩa function. Nếu bạn bỏ `return` thì kết quả sẽ là `None`, function `least_difference` sẽ không trả về giá trị gì.

## Docstrings

Docstrings là cách bạn viết giải thích cho function của mình để hỗ trợ những người sử dụng function của bạn hiểu cách hoạt động và logic bên trong.

```python
def least_difference(a, b, c):
    """Return the smallest difference between any two numbers
    among a, b and c.

    >>> least_difference(1, 5, -5)
    4
    """
    diff1 = abs(a - b)
    diff2 = abs(b - c)
    diff3 = abs(a - c)
    return min(diff1, diff2, diff3)

print(help(least_difference))
```

Docstrings sẽ được hiển thị nếu bạn đặt tên function của bạn vào function `help()` (chú ý chỉ có tên function, không truyền arguments, không có dấu đóng mở ngoặc `()`).

Docstrings bắt đầu bằng ba dấu nháy đơn `'''` hoặc kép `"""`, đây là cú pháp Python cho phép bạn viết string có nhiều dòng.

Dấu `>>>` trong docstrings là quy ước đại diện cho môi trường Python interactive shells (môi trường chạy code Python và hiển thi kết quả ngay bên dưới). Ký hiệu `>>>` giúp người đọc hình dung code ví dụ chạy như thế nào.

Viết docstrings cho function của bạn là một thói quen thiết yếu khi lập trình. Bạn chính là người sẽ cảm ơn đầu tiên khi mở code của mình ra sau vài tháng không làm việc trên dự án đó. Đây là một ví dụ docstrings ngoài thực tế của thư viện `numpy`: [numpy function np.eye()](https://github.com/numpy/numpy/blob/v1.14.2/numpy/lib/twodim_base.py#L140-L194)

## Default arguments

Tham số mặc định **default argument** là tham số mà bạn định nghĩa giá trị mặc định cho nó. Khi function được gọi, nếu không có giá trị nào được truyền vào, default arguments sẽ lấy giá trị mặc định. Ví dụ:

```python
def greeting(place='CoderSchool'):
    print('Welcome to', place)

greeting()  # Output: Welcome to CoderSchool
greeting('HCMC')  # Output: Welcome to HCMC
```

Lưu ý: nếu bạn có arguments khác không phải default arguments, chúng phải đứng trước default arguments:

```python
# WRONG: SyntaxError: non-default argument follows default argument
def greeting(place='CoderSchool', name):
    print('Hello', name, 'Welcome to', place)

# CORRECT
def greeting(name, place='CoderSchool'):
    print('Hello', name, 'Welcome to', place)

greeting('Minh')  # Output: Hello Minh Welcome to CoderSchool
greeting('Minh', 'HCMC')  # Hello Minh Welcome to HCMC
```

## Nâng cao và mở rộng

**Một function có thể làm argument cho function khác:**

```python
def square(x):
    return x * x

def calc(fn, x):
    return fn(x)

print(calc(square, 2))  # Output: 4
print(calc(square, calc(square, 2))) # Output: 16
```

Trong ví dụ trên:

- Function `square` trả về bình phương của argument x. Ví dụ `square(2)` trả về `4`, `square(3)` trả về `9`.
- Function `calc` có 2 arguments `fn` và `x`, trong đó `fn` là một function. Lệnh gọi function `fn` được thực thi bên trong function `calc` ở câu lệnh `return`.
- Ở câu lệnh `print(calc(square, 2))`, Python sẽ gọi function `calc` với tham số là function `square` và `2`. Function `square(2)` sẽ được thực thi bên trong `calc` và trả về kết quả là `4`.
- Ở câu lệnh `print(calc(square, calc(square, 2)))`, đầu ra của `calc(square, 2)` là `4` sẽ được tiếp tục truyền vào hàm `calc` và tính toán tiếp cho ra kết quả `16`.
- Function `calc` trong ví dụ trên được gọi là một **high order functions**

Đây là một ví dụ đơn giản, nhưng có thể tương đối khó hiểu cho người mới bắt đầu, bạn nên dành thời gian hiểu thấu đáo ví dụ này. Việc lồng ghép function, truyền function dạng argument, ... mở ra khả năng tạo ra những đoạn lệnh rất phức tạp chỉ với những cú pháp đơn giản đã học. Đây cũng là một điểm đặc biệt mang lại sức mạnh gần như không giới hạn cho lập trình.

**Function có thể gọi chính bản thân bên trong nó (Recursive Function)**

_Lưu ý, đây là khái niệm khó, phần này mang tính giới thiệu là chính_

Hàm đệ quy hay **recursive function** là khái niệm function được gọi trong code của chính nó. Nó có thể tạo ra một vòng lặp vô hạn. Trong một số bài toán, phương pháp này cho lời giải rất gọn gàng. Ví dụ, function tính giai thừa của một số cho trước:

```python
# Recursive function factorial_recursion()
def factorial_recursion(n):
   if n == 1:
       return n
   else:
       return n*factorial_recursion(n-1)

# Call the function
num = 7
print("The factorial of ",num," is ",factorial_recursion(num))
```
