Hướng dẫn is none python - không phải trăn sao

Bài viết này nêu lên một số khía cạnh thú vị [nhưng cũng rắc rối] của kiểu dữ liệu None cùng các phép toán liên quan đến nó, qua đó giúp các bạn mới học hiểu sâu sắc hơn về các kiểu dữ liệu có trong Python. Bài viết này có sử dụng một số khái niệm có trong lý thuyết nhóm chỉ nhằm mục đích minh họa những ý đồ của người viết.

1. Khái niệm phần tử không

Trong lý thuyết nhóm có khái niệm về phần tử không hay phần tử trung hòa. Phần tử không θ của một tập S trên phép toán * là phần tử thỏa mãn: a*θ = θ*a = a với mọi a trên S.θ của một tập S trên phép toán * là phần tử thỏa mãn: a*θ = θ*a = a với mọi a trên S.

Các kiểu dữ liệu cơ bản trong Python cũng có phần tử không như vậy. Xem bảng tổng kết sau:

Kiểu dữ liệuPhép toánPhần tử khôngVí dụ
Số nguyên + 0 0 + 69 = 69 + 0
Số thực + 0.0 0 + 69 = 69 + 0
Số thực 0.0 + 96.0 = 96.0 + 0.0 Danh sách +, extend
[] + 0 + 69 = 69 + 0 Số thực
0.0 + 96.0 = 96.0 + 0.0 Danh sách +, extend []
[1] + [] = [] + [1] = [1] + 0 + 69 = 69 + 0 Số thực
0.0 + 96.0 = 96.0 + 0.0 Danh sách +, extend []
[1] + [] = [] + [1] = [1] + 0 + 69 = 69 + 0 Số thực
0.0 + 96.0 = 96.0 + 0.0 Danh sách +, extend []

[1] + [] = [] + [1] = [1]

tuple là một tập hợp đặc biệt, chỉ có chính nó, mà cũng không phải là chính nó. Không phải là chính nó vì None bao hàm ý nghĩa là thiếu giá trị [denoting lack of value]:

[] type[None]

[1,] + [] = [] + [1,] = [1,] tương tác với tất cả các phần tử không:

Tập hợp assert[[[] and None] == []] >>> assert[[{} and None] == {}] >>> assert[[0.0 and None] == 0.0] >>> assert[["" and None] == ""] >>> assert[[set[[]] and None] == set[[]]] >>> assert[[[] and None] == []] >>> assert[[0j and None] == 0J] >>> assert[[False and None] == False]

union S là tập hợp các phần tử không, bao gồm chính None, thì với phép toán and, None chính là phần tử không bên phải của S. Ai bảo None không phải là giá trị.

set[[]]

set[[1]].union[set[[]]] = set[[]].union[set[[1]]] = set[[1]] assert[[None and []] == None] >>> assert[[None and {}] == None] >>> assert[[None and set[[]]] == None] >>> assert[[None and ""] == None] >>> assert[[None and 0] == None]

Chuỗi

"" assert[[None or set[[]]] == set[[]]] >>> assert[[None or []] == []] >>> assert[[None or {}] == {}] >>> assert[[None or ""] == ""] >>> assert[[None or 0] == 0] >>> assert[[None or 0j] == 0j] >>> assert[[None or []] == []]

"abc" + "" = "" + "abc" = "abc" None là phần tử không bên phải đối với tập S nói trên trong phép toán or.

Từ điển

update assert[[{} or None] is None] >>> assert[[[] or None] is None] >>> assert[[0 or None] is None] >>> assert[[set[[]] or None] is None] >>> assert[["" or None] is None] >>> assert[[0j or None] is None] >>> assert[[[] or None] is None] >>> assert[[0.0 or None] is None]

{} None tương tác với các phần tử không, thứ tự các toán hạng là điều bạn cần chú ý.

{1:1}.update[{}] = {}.update[{1:1}] = {1:1} or giữa None và object bất kỳ không phải là phần tử không là ánh xạ đồng nhất bất kể thứ tự phép toán:

Số phức set[['a']] or None set[['a']] >>> None or set[['a']] set[['a']] >>> None or "abc" 'abc' >>> "abc" or None 'abc' >>> None or {1:1} {1: 1} >>> {1:1} or None {1: 1}

0 + 0j and thì luôn cho kết quả None với bất kỳ phần tử nào không phải là phần tử không, không kể thứ tự toán hạng:

  assert[[None and 1] is None] >>> assert[[1 and None] is None] >>> assert[[[1] and None] is None] >>> assert[[None and [1]] is None] >>> assert[["abc" and None] is None] >>> assert[[None and "abc"] is None]

Logic None có thể trả về None, nghĩa là không có giá trị. Điều này làm cho None trong python trở lên phức tạp và không giống với null trong C# hay nothing trong VB.NET. Trong VB.NET một biểu thức logic luôn luôn trả về giá trị logic.

or là tận cùng [bottom], là nhỏ hơn tất cả.

False None > type[None]None cùng các tương tác của nó với các phần tử không qua các phép toán logic là RẤT quan trọng khi bạn viết các lệnh if, filter...

None tương tác với tất cả các phần tử không:None nếu bạn viết return None, hoặc không return ở bất kỳ chỗ nào trong hàm. Một hàm như vậy khi tham gia vào biểu thức logic sẽ tạo ra những hiệu ứng mà bạn cần phải nắm rõ bản chất.

>>> assert[[[]andNone]==[]]>>> assert[[{}andNone]=={}]>>> assert[[0.0andNone]==0.0]>>> assert[[""andNone]==""]>>> assert[[set[[]]andNone]==set[[]]]>>> assert[[[]andNone]==[]]>>> assert[[0jandNone]==0J]>>> assert[[FalseandNone]==False]

Nếu ta gọi S là tập hợp các phần tử không, bao gồm chính None, thì với phép toán and, None chính là phần tử không bên phải của S. Ai bảo None không phải là giá trị.filter. filter cùng với hàm func sẽ loại bỏ tất cả các phần tử trong danh sách mà tác động của hàm func lên phần tử này tạo ra phần tử không. Diễn giải dễ hiểu của nó như sau:

Tuy nhiên:

>>> assert[[Noneand[]]==None]>>> assert[[Noneand{}]==None]>>> assert[[Noneandset[[]]]==None]>>> assert[[Noneand""]==None]>>> assert[[Noneand0]==None] def filter[func, list]: return [x for x in list if func[x] not in S]

Tương tự:

>>> assert[[Noneorset[[]]]==set[[]]]>>> assert[[Noneor[]]==[]]>>> assert[[Noneor{}]=={}]>>> assert[[Noneor""]==""]>>> assert[[Noneor0]==0]>>> assert[[Noneor0j]==0j]>>> assert[[Noneor[]]==[]]filter[lambda x: not x, [3, 4, False, True, {1: 0}, []]] [False, []]

Nghĩa là None là phần tử không bên phải đối với tập S nói trên trong phép toán or.

def filter[func, list]: return [x for x in list if x not in S] return [x for x in list if x not in S]

Cuối cùng một cách viết gây khó hiểu là thay thế lambda x: x bằng hàm None.None.

filter[None, list] # filter[lambda x: x, list]

Ví dụ:

>>> filter[None,[0,0.0,"",0+0j,set[[]],[],[],{},False]][]>>> filter[None,["","abc"," "]]['abc', ' ']>>> filter[None,[1,0,2,0.0]][1, 2]filter[None, [0, 0.0, "", 0+0j, set[[]], [], [], {}, False]] [] >>> filter[None, ["", "abc", " "]] ['abc', ' '] >>> filter[None, [1, 0, 2, 0.0]] [1, 2]

Ở đây chúng ta có cảm giác như None được dùng như một hàm. Thực ra không phải vậy, None có nghĩa là không có hàm nào ở đây cả, nói cách khác đối số đầu tiên của filter bị khuyết. Python lúc đó sẽ dùng hàm mặc định gì đó tương tự như lambda x: x.None được dùng như một hàm. Thực ra không phải vậy, None có nghĩa là không có hàm nào ở đây cả, nói cách khác đối số đầu tiên của filter bị khuyết. Python lúc đó sẽ dùng hàm mặc định gì đó tương tự như lambda x: x.

4. Dùng None với map

>>> map[None,[1,2,{1:2}]][1, 2, {1: 2}]map[None, [1, 2, {1:2}]] [1, 2, {1: 2}]

map không thay đổi danh sách khi nó bị khuyết hàm tác động. Khi đó hàm None tương đương với ánh xạ đồng nhất [mặc dù không chính xác, vì thực ra là không có hàm nào cả, Python có thể đã sử dụng hàm mặc định]. Tuy nhiên dùng hàm None khi có hai danh sách trở lên thì lại tạo ra khả năng đặc biệt. không thay đổi danh sách khi nó bị khuyết hàm tác động. Khi đó hàm None tương đương với ánh xạ đồng nhất [mặc dù không chính xác, vì thực ra là không có hàm nào cả, Python có thể đã sử dụng hàm mặc định]. Tuy nhiên dùng hàm None khi có hai danh sách trở lên thì lại tạo ra khả năng đặc biệt.

>>> map[None,[1,2],[3,4]][[1, 3], [2, 4]]>>> map[None,[1,2],[3,4],[5,6]][[1, 3, 5], [2, 4, 6]]map[None, [1, 2], [3, 4]] [[1, 3], [2, 4]] >>> map[None, [1, 2], [3, 4], [5, 6]] [[1, 3, 5], [2, 4, 6]]

Khả năng này tương đương với zip.zip.

>>> zip[[1,2],[3,4],[5,6]][[1, 3, 5], [2, 4, 6]]>>> zip[[1,2],[3,4]][[1, 3], [2, 4]]zip[[1, 2], [3, 4], [5, 6]] [[1, 3, 5], [2, 4, 6]] >>> zip[[1, 2], [3, 4]] [[1, 3], [2, 4]]

Diễn giải của nó như sau:

>>> map[lambdax,y:[x,y],[1,2],[3,4]][[1, 3], [2, 4]]>>> map[lambdax,y,z:[x,y,z],[1,2],[3,4],[5,6]][[1, 3, 5], [2, 4, 6]]map[lambda x, y: [x, y], [1, 2], [3, 4]] [[1, 3], [2, 4]] >>> map[lambda x, y, z: [x, y, z], [1, 2], [3, 4], [5, 6]] [[1, 3, 5], [2, 4, 6]]

Một lần nữa trong mục này, mặc dù None bao hàm ý nghĩa về sự khuyết giá trị, song trong triển khai của hàm bất kỳ việc khuyết giá trị dẫn đến việc sử dụng các hàm mặc định. Lúc đó None có ý nghĩa là những gì mặc định. Đôi khi có thể ngắn gọn coi nó cũng là một hàm đặc biệt, hàm None.None bao hàm ý nghĩa về sự khuyết giá trị, song trong triển khai của hàm bất kỳ việc khuyết giá trị dẫn đến việc sử dụng các hàm mặc định. Lúc đó None có ý nghĩa là những gì mặc định. Đôi khi có thể ngắn gọn coi nó cũng là một hàm đặc biệt, hàm None.

Chú ý quan trọng: Các test của bài viết này được thử trên python 2.5.x.python 2.5.x.

Bài Viết Liên Quan

Chủ Đề