def execute[func]:
print['Before execution']
func[]
print['After execution']
2 cũng hỗ trợ chúng ta trong việc lồng các functions. Nó có nghĩa là chúng ta có thể định nghĩa một function trong body hoặc định nghĩa một function khác. Chúng ta cùng lấy 1 ví dụ khác cho điều này:def foo[x]:
def bar[y]:
return x+y
return bar
Ở ví dụ trên, mình đã sử dụng 2 khái niệm được nói ở trên:
- Trả về một function [
6] dưới dạng value trả về của function>>> execute[say_hello] Before execution Hello world! After execution
7.>>> execute[say_hello] Before execution Hello world! After execution
- Lồng function
6 trong định nghĩa của function>>> execute[say_hello] Before execution Hello world! After execution
7.>>> execute[say_hello] Before execution Hello world! After execution
Giờ chúng ta cùng chạy đoạn code trên nha.
>>> v1 = foo[3]
Ở đây,
def foo[x]:
def bar[y]:
return x+y
return bar
0 lưu trữ value trả về của function >>> execute[say_hello]
Before execution
Hello world!
After execution
7, tức là function >>> execute[say_hello]
Before execution
Hello world!
After execution
6. Điều gì sẽ xảy ra nếu chúng ta gọi def foo[x]:
def bar[y]:
return x+y
return bar
0 với một vài tham số?>>> print[v1[7]]
10
Khi một function được xử lý dưới dạng data [trong trường hợp này là trả về dưới dạng value từ một function khác], nó ngầm mang thông tin cần thiết để thực thi. Điều này được gọi là tính đóng gói [closure] trong Python. Chúng ta có thể kiểm tra việc đóng gói của function bằng cách sử dụng thuộc tính
def foo[x]:
def bar[y]:
return x+y
return bar
4 của function. Nó sẽ trả về cho chúng ta một def foo[x]:
def bar[y]:
return x+y
return bar
5 chứa tất cả các closures của function đó. Nếu chúng ta muốn xem bất kỳ nội dung nào của closure, chúng ta có thể làm như dưới đây.>>> v1.__closure__
[,]
>>> v1.__closure__[0].cell_contents
3
Chúng ta đã biết được cả 2 thuộc tính của function, hãy xem chúng ta có thể sử dụng các thuộc tính này trong các tình huống thực tế nha.
Giả sử chúng ta muốn thực hiện một số chức năng chung trước hoặc sau khi thực hiện function. Nó có thể giống như một lệnh hiển thị thời gian thực hiện của function chẳng hạn.
Một cách dễ dàng để làm điều này là viết bất kì điều gì trước và sau khi thực hiện dưới dạng các dòng code trước và sau tương ứng. Ví dụ:
def say_hello[]:
print['Hello world!']
0Nhưng đây có thực sự là một cách tốt để thực hiện? Như mình nói ở trên, đây là một chức năng chung nên điều gì sẽ xảy ra nếu chúng ta nhiều hơn 1 function và chúng ta phải thực hiện cùng một đoạn code cho tất cả function khác?
def say_hello[]:
print['Hello world!']
1Function
>>> execute[say_hello]
Before execution
Hello world!
After execution
3 chỉ in ra def foo[x]:
def bar[y]:
return x+y
return bar
7. Còn function def foo[x]:
def bar[y]:
return x+y
return bar
8 nhận một function làm đối số và tạo ra một function khác là def foo[x]:
def bar[y]:
return x+y
return bar
9 trong định nghĩa của nó. def foo[x]:
def bar[y]:
return x+y
return bar
9 thực hiện một số câu lệnh in trước và sau khi thực hiện function được truyền vào dưới dạng đối số cho def foo[x]:
def bar[y]:
return x+y
return bar
8.Giờ chúng ta truyền function
>>> execute[say_hello]
Before execution
Hello world!
After execution
3 vào trong def foo[x]:
def bar[y]:
return x+y
return bar
8 nha.def say_hello[]:
print['Hello world!']
2>>> v1 = foo[3]
4 là một function khác được return từ function def foo[x]:
def bar[y]:
return x+y
return bar
8. Vậy thì output của function >>> v1 = foo[3]
4 sẽ như thế nào? Let's check it.def say_hello[]:
print['Hello world!']
3Và điều gì sẽ xảy ra nếu chúng ta nếu chúng ta gán lại hàm mới được trả về từ function
def foo[x]:
def bar[y]:
return x+y
return bar
8 cho function >>> execute[say_hello]
Before execution
Hello world!
After execution
3?def say_hello[]:
print['Hello world!']
4Chúng ta đã thay đổi chức năng của của function
>>> execute[say_hello]
Before execution
Hello world!
After execution
3 mà không thay đổi đoạn code của chính function này.Vậy tiếp theo sẽ là gì? Nếu đã đọc đến đây, thì chúng ta đã tìm hiểu xong về bản chất của
>>> print[v1[7]]
10
0 rồi đó. Mình sẽ giải thích thêm nha.3. Decorator
>>> print[v1[7]]
10
0 là function cho phép chúng ta có thể tự do mở rộng hoặc chỉnh sửa function một cách linh hoạt mà không cần thực hiện thay đổi code ban đầu của nó.Trong ví dụ tren, hàm
def foo[x]:
def bar[y]:
return x+y
return bar
8 cung cấp cho chúng ta chức năng này [nó thay đổi output của hàm >>> execute[say_hello]
Before execution
Hello world!
After execution
3]. Vì vậy, def foo[x]:
def bar[y]:
return x+y
return bar
8 được gọi là >>> print[v1[7]]
10
0. Thay vì truyền thẳng >>> execute[say_hello]
Before execution
Hello world!
After execution
3 đến def foo[x]:
def bar[y]:
return x+y
return bar
8, chúng ta có thể viết tắt:def say_hello[]:
print['Hello world!']
5Mình hy vọng các bạn đã hiểu được
>>> print[v1[7]]
10
0 là gì. Có khi nào bạn tự hỏi tại sao chúng ta cần return một function từ def foo[x]:
def bar[y]:
return x+y
return bar
8? Mà chúng ta chỉ cần gọi function def foo[x]:
def bar[y]:
return x+y
return bar
8, trong đó chúng ta có thể in các dòng lệnh cùng với việc thực hiện function đối số?def say_hello[]:
print['Hello world!']
6Giả sử, mình đồng ý với gợi ý này. Nhưng mình cũng có một vài câu hỏi:
- Giờ đây,
3 sẽ lưu giá trị là gì? Nó có thể gọi luôn được không?.>>> execute[say_hello] Before execution Hello world! After execution
=>
>>> execute[say_hello]
Before execution
Hello world!
After execution
3 sẽ lưu giá trị None là giá trị trả về cho >>> v1.__closure__
[,]
>>> v1.__closure__[0].cell_contents
3
3. Nên chúng ta không thể gọi >>> execute[say_hello]
Before execution
Hello world!
After execution
3 ngay lập tức.- Điều gì sẽ xảy ra nếu chúng ta muốn mở rộng một function có một vài đối số như dưới đây:
def say_hello[]:
print['Hello world!']
7Nhưng vấn đề ở đây là: làm thế nào để nhận được giá trị của
>>> v1.__closure__
[,]
>>> v1.__closure__[0].cell_contents
3
5 và >>> v1.__closure__
[,]
>>> v1.__closure__[0].cell_contents
3
6 tại thời điểm truyền bất kỳ function nào tới >>> v1.__closure__
[,]
>>> v1.__closure__[0].cell_contents
3
7?def say_hello[]:
print['Hello world!']
8Ở đây, chúng ta không thể lấy được giá trị của
>>> v1.__closure__
[,]
>>> v1.__closure__[0].cell_contents
3
5 và >>> v1.__closure__
[,]
>>> v1.__closure__[0].cell_contents
3
6.Mình hy vọng 2 câu hỏi này có thể giải thích được tại sao
>>> print[v1[7]]
10
0 cần phải return một function.4. Một vài ví dụ về >>> print[v1[7]]
10
0
>>> print[v1[7]]
10
- Tính thời gian thực hiện một function:
def say_hello[]:
print['Hello world!']
9- Hoặc trong một ứng dụng web, nó có thể sử dụng để kiểm tra user đã login hay chưa:
>>> say_hi = say_hello
05. Lời kết
Cảm ơn các bạn đã đọc đến đây. Mình hy vọng bài viết này có thể cung cấp những kiến thức cơ bản nhất về
>>> print[v1[7]]
10
0 trong Python và một số trường hợp sử dụng. Nếu bạn có một số gợi ý để có thể giúp mọi người tiếp cận đến >>> print[v1[7]]
10
0 một cách dễ hiểu nhất, hãy comment ở bên dưới nha.