Skip to main content

[Python] function là object

Nếu có coi function là một cái gì đó đặc biệt, khác biệt với mọi thứ còn lại trong Python thì có thể bạn đã sai, hay ít nhất cũng cần nghĩ lại sau khi xem các đặc điểm của function trong bài này.

Python lambda
Function là object, như mọi thứ khác trong Python. Integer là object, string là object, và function không phải ngoại lệ.
$ python3
>>> type(5)
<class 'int'>
>>> type('http://pymi.vn')
<class 'str'>
>>> type(True)
<class 'bool'>
>>> type(len)
<class 'builtin_function_or_method'>
Nếu biết về lambda trong Python, bạn sẽ thấy rõ hơn function là cái gì:
>>> double = lambda x: x*2
>>> type(double)
<class 'function'>
>>> double(21)
42
lambda tạo ra 1 object kiểu function (tưởng tượng ra 1 cục tròn tròn), sau đó ta gán (bind) tên ``double`` cho object đó. Nó tương tự như việc gán tên cho 1 string:

>>> name = "PyMI"
>>> type(name)
<class 'str'>
name -----> (string PyMI)
double ------> (function x:x*2)

Bản chất cú pháp định nghĩa function trong python là nó sẽ tạo ra một function object, và bind cái tên của function vào object ấy.
>>> def double(x):
...     return x*2
...
>>> type(double)
<class 'function'>
>>> double(7)
14
Để bind một cái tên khác vào cục function object này, gán tên mới như bình thường:
>>> gap_doi = double
>>> gap_doi(7)
14
Phép gán (=) thực chất nói rằng: tạo ra một cái tên và bind nó vào cái cục object mà double đang bind tới.

gap_doi ----> (function object) <----- double

Function là  callable object

function là object như bao object khác, điều mà khiến nó có vẻ khác biệt là bởi khả năng "gọi" được, tức viết được theo dạng
function(argument) 
khả năng này có được nhờ function object có method tên là __call__.
Một object có method __call__ gọi là 1 callable object: có thể kể tới function, class hay bất cứ kiểu dữ liệu nào thoả mãn điều kiện ấy.
>>> len.__call__([1,2,3])
3
>>> len([1,2,3])
3
>>> class Foo():
...     pass
...
>>> Foo.__call__()
<__main__.Foo object at 0x10d8c3b70>
>>> Foo()
<__main__.Foo object at 0x10d8c3898>

Function nhận đầu vào là function 

Function mà nhận function khác làm đầu vào được gọi là "higher order function".

``len`` là một function
>>> id(len)
4517823904
id là function có thể nhận đầu vào là một function, id là một "higher order function".

Function ``do`` sau đây là một higher order function:
>>> def do(function, argument):
...     return function(argument)
...
>>> result = do(lambda x:x*2, 'Python')
>>> print(result)
PythonPython
Các decorator đều là các higher order function.

map

map là higher order function thường được dùng.
map nhận đầu vào là 1 function và 1 list (chính xác hơn thì là iterable), rồi map gọi function ấy với từng phần tử của list, thu được 1 tập các kết quả sau khi gọi function.
>>> map(lambda x: x*2, [1,3,5])
<map object at 0x10d6b5128>
>>> list(map(lambda x: x*2, [1,3,5]))
[2, 6, 10]
Nếu không thấy quen dùng lambda, có thể viết dài hơn sử dụng cú pháp def:
>>> def double(n):
...     return n*2
...
>>> list(map(double, [1,3,5]))
[2, 6, 10]
Function là object, tức ta có thể tạo 1 list các function:
>>> funcs = [id, type, str, len]
>>> type(funcs[0])
<class 'builtin_function_or_method'>
>>> for func in funcs:
...     print(func.__name__, func(['Python', 'Golang']))
...
id 4520086984
type <class 'list'>
str ['Python', 'Golang']
len 2

Lambda với list comprehension

Tạo 5 function, mỗi function in một số từ 0 đến 4
Tạo 1 list 5 function bằng list comprehension:
>>> fs = [lambda: print(x) for x in range(5)]
>>> for f in fs:
...     f()
...
4
4
4
4
4
Cả 5 function ở đây đều refer đến "i", vì thế ta không thu được 5 functions lần lượt in từ 0 đến 4.
Cách làm đúng:
>>> import functools
>>> for f in [functools.partial(lambda x:print(x), x) for x in range(5)]:
...     f()
...
0
1
2
3
4
Function là object.
Hết.
Welcome to functional programming and Python 😱
HVN at http://www.familug.org/ and http://pymi.vn 

Comments

Popular posts from this blog

Tài liệu và hướng dẫn học Python

Để tiết kiệm thời gian, tốt nhất là đi học PyMI Updated: 130617 Sau đây là các tài liệu khuyên dùng: Vì nhiều lý do, nên học python2.7 tại thời điểm hiện tại (giờ là tháng 6/2013 - muốn biết tại sao thì tự tìm hiểu) python 3.5+ (giờ là tháng 2/2017) Chuẩn bị: 1. biết bật tắt máy 2. biết cài python 3. tập gõ 10 ngón - gõ 2 ngón hay 1 ngón cũng không sao, nhưng 10 ngón là cách dễ nhất để gõ nhanh nhất. Tài liệu - Nên dùng tài liệu tại trang chủ của Python làm chính, tham khảo thêm các tài liệu khác tại http://www.familug.org/2016/12/free-ebook.html Căn bản, mới học 1.1 Python PyMI.vn https://pymi.vn/tutorial/ 1.2. Python offical tutorial kết hợp làm bài tập trên HackerRank  (đề bài bằng tiếng Anh, nhưng Google translate 1 lúc cũng ra vì có nhiều ví dụ mẫu đi kèm). Học viên của Pymi.vn có rất nhiều học viên đã tự học với Learn Python the hard way nhưng chưa thấy ai thành công cả. Hai link dưới nên đọc sau khi đã nắm được những phần cơ bản của ngôn ngữ pytho...

The PyMiers

New FAMILUG