Trong phần này chúng ta sẽ tìm hiểu về các toán tử có trong Python.
Toán tử ở đây là các kí tự dùng để thực thi các phép tính nào đó. Hầu hết các toán tử trong lập trình đều bắt nguồn từ các phép toán trong toán học. Chỉ khác là trong lập trình thì toán tử thao tác với dữ liệu.
Trong Python, toán tử được chia ra làm những loại sau:
- Toán tử số học
- Toán tử boolean
- Toán tử quan hệ
- Toán tử thao tác bit
Trong một biểu thức toán tử có thể có một hoặc hai toán hạng. Toán hạng là các giá trị hay các biến tham gia vào biểu thức. Toán tử sẽ xử lý các toán hạng và trả về kết quả. Ví dụ a = 1 + c, trong đó dấu = và dấu + là các toán tử, còn a, 1 và c là các toán hạng.
Dấu + và – trong toán tử cộng trừ có thể được dùng để làm dấu của số. Nhưng thường thì chúng ta chỉ dùng dấu – để biểu diễn số nguyên âm chứ ít ai dùng dấu + để biểu diễn số nguyên dương.
>>> a = 1 >>> -a -1 >>> -(-a) 1
Toán tử gán
Toán tử gán có kí hiệu là dấu =, ý nghĩa của toán tử này là gán một giá trị cho một biến nào đó. Toán hạng nằm bên trái dấu = sẽ được gán giá trị.
>>> x = 1 >>> x 1
Trong đoạn code trên chúng ta gán x bằng 1.
>>> x = x + 1 >>> x 2
Trong đoạn code kế tiếp thì biểu thức x = x + 1 không có ý nghĩa trong toán học. Nhưng trong lập trình thì hợp lệ. Biểu thức đó có ý nghĩa tăng giá trị của x lên 1. Ở bên phải toán tử, biểu thức x + 1 có giá trị là 2 sẽ được gán cho biến x.
>>> a = b = c = 4 >>> print (a, b, c) 4 4 4
Trong Python và hầu hết các ngôn ngữ lập trình, chúng ta có thể gán 1 giá trị cho nhiều biến cùng một lúc.
>>> 3 = y File "<stdin>", line 1 SyntaxError: can't assign to literal
Đoạn code trên báo lỗi vì bạn chỉ có thể gán giá trị hoặc biến cho một biến chứ không thể gán cho một giá trị khác.
Toán tử số học
Bảng dưới đây mô tả các toán tử số học trong Python.
Kí HIỆU | TÊN |
---|---|
+ |
Cộng |
- |
Trừ |
* |
Nhân |
/ |
Chia |
// |
Floor division |
% |
Chia lấy phần dư |
** |
Lũy thừa |
Đoạn code dưới đây ví dụ về các toán tử trên.
a = 10 b = 11 c = 12 add = a + b + c sub = c - a mult = a * b div = c / 3 pow = a ** 2 print (add, sub, mult, div) print (pow)
Tất cả các toán tử này đều có trong toán học.
33 2 110 4.0 100
Kết quả trả về.
print (9 / 3) print (9 / 4) print (9 / 4.0) print (9 // 4.0) print (9 % 4)
Đoạn code trên ví dụ rõ hơn về phép toán chia.
print (9 // 4.0)
Dòng trên ví dụ về toán tử //, đây là toán tử làm tròn xuống, ví dụ 2.25 hay 2.75 đều được làm tròn về 2.0.
print (9 % 4)
Toán tử % là phép toán lấy phần dư. Ví dụ 9 chia 4 được 2 dư 1.
3.0 2.25 2.25 2.0 1
>>> 'return' + 'of' + 'the' + 'king' 'returnoftheking'
Trong các bài trước, chúng ta đã biết là toán tử cộng có thể được dùng để nối string.
>>> 3 + ' apples' Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unsupported operand type(s) for +: 'int' and 'str'
Chúng ta không thể cộng một số với một string. Kết quả sẽ cho ra một lỗi exception.
>>> str(3) + ' apples' '3 apples'
Nếu muốn chuyển một số sang chuỗi để nối vào một chuỗi thì chúng ta phải dùng hàm str()
để chuyển.
Tuy nhiên toán tử * lại có thể dùng cho chuỗi và số.
>>> 'dollar ' * 5 'dollar dollar dollar dollar dollar '
Toán tử boolean
Trong Python, chúng ta có các toán tử and
, or
và not
. Các toán tử này làm công việc mang tính logic. Chúng thường được dùng trong các câu lệnh if
và while.
# andop.py print (True and True) print (True and False) print (False and True) print (False and False)
Đoạn code trên ví dụ về các toán tử and
. Kết quả chỉ trả về True khi cả hai đều là True.
True False False False
Đoạn code dưới đây ví dụ về toán tử or.
Kết quả trả về True khi một trong hai toán hạng là True.
print (True or True) print (True or False) print (False or True) print (False or False)
True True True False
Toán tử not
chỉ làm việc với một toán hạng. Toán tử này sẽ đảo ngược giá trị từ True thành False và ngược lại.
print (not False) print (not True) print (not ( 4 < 3 ))
True False True
Hai toán tử and
và or
chỉ xét tới toán hạng thứ hai khi toán hạng thứ nhất thỏa điều kiện. Ví dụ trong toán tử and
nếu toán hạng đầu tiên là false thì tự động kết quả trả về sẽ là false chứ không xét toán hạng thứ 2 nữa, còn đối với toán tử or
thì nếu toán hạng đầu tiên là True thì lập tức kết quả trả về là True luôn chứ cũng không xét toán hạng thứ hai nữa.
Ví dụ.
x = 10 y = 0 if (y != 0 and x/y < 100): print ("a small value")
Đoạn code trên sẽ trả về False vì y khác 10 và toán hạng thứ hai không được xét đến. Nếu không sẽ xảy ra lỗi exception vì chúng ta không thể chia một số cho 0.
Toán tử quan hệ
Các toán tử quan hệ dùng để so sánh các giá trị, kết quả trả về là True hoặc False.
KÍ HIỆU | Ý NGHĨA |
---|---|
< |
Bé hơn |
<= |
Bé hơn hoặc bằng |
> |
Lớn hơn |
>= |
Lớn hơn hoặc bằng |
== |
Bằng |
!= or <> |
Không bằng (khác) |
is |
định danh đối tượng |
is not |
định danh không phải đối tượng |
Bảng trên mô tả các toán tử quan hệ.
>>> 3 < 4 True >>> 4 == 3 False >>> 4 >= 3 True
Chúng ta không chỉ có thể dùng các toán tử quan hệ với các số mà có thể dùng với các đối tượng khác nữa, mặc dù làm thế cũng không ý nghĩa mấy.
>>> "six" == "six" True >>> "a" > 6 True >>> 'a' < 'b' True
Chúng ta có thể so sánh hai string, hai kí tự hoặc so sánh một string với một số.
>>> 'a' < 'b'
Trong máy tính thì các kí tự này đều mang một mã số bên mình, khi so sánh hai kí tự thì thực chất máy tính so sánh hai mã số này. Mã số của các kí tự này được lưu trong các bảng mã. Mặc định là bảng mã ASCII.
print ('a' < 'b') print ("a is:", ord('a')) print ("b is:", ord('b'))
Nếu như bạn muốn biết mã số của các kí tự thì bạn có thể dùng hàm ord().
True a is: 97 b is: 98
Như vậy trong máy tính khi so sánh hai kí tự ‘a’ và ‘b’ thực chất là so sánh hai số 97 và 98.
>>> "ab" > "aa" True
Khi so sánh một chuỗi, các kí tự đầu tiên sẽ được so sánh với nhau, nếu chúng bằng nhau, các kí tự thứ 2, thứ 3…. sẽ lần lượt được so sánh. Thực ra chúng ta cũng ít khi so sánh hai chuỗi vì việc này cũng không có ý nghĩa mấy.
print (None == None) print (None is None) print (True is True) print ([] == []) print ([] is []) print ("Python" is "Python")
Toán tử ==
có tác dụng kiểm tra xem hai toán hạng có bằng nhau hay không. Từ khóa is
kiểm tra xem toán hạng có phải là một đối tượng kiểu nào đó hay không.
True True True True False True
Đoạn tiếp theo có thể sẽ hơi khó hiểu nhưng bạn cũng không cần đọc làm gì 😀
Sự khác nhau giữa toán tử ==
và từ khóa is
là khi chúng được sử dụng trên các đối tượng thì toán tử ==
sẽ so sánh các giá trị trong khi từ khóa is
sẽ so sánh địa chỉ của chúng trong bộ nhớ. Do đó trong biểu thức []==[]
kết quả trả về True vì chúng đều là các list rỗng, nhưng []is[]
lại cho kết quả False vì chúng là các thực thể khác nhau trong bộ nhớ. Còn đối với các đối tượng None, True thì lại khác, đây là các đối tượng đặc biệt, trong Python chúng là duy nhất, không hề có 2 đối tượng None hay True nên kết quả trả về True. Đối với trường hợp so sánh 2 string ("Python" is "Python")
thì do Python tự động tối ưu bộ nhớ nên những string có giá trị giống nhau sẽ được sử dụng chung bộ nhớ, kết quả trả về True.
Toán tử thao tác bit
Đối với loài người chúng ta thì chúng ta sử dụng bộ chữ số hệ thâp phân (tức hệ 10) gồm các chữ số từ 0 đến 9, bộ chữ số này rất tiện cho chúng ta vì mặc nhiên chúng ta có 10 ngón tay và 10 ngón chân. Đối với máy tính thì khác, máy tính chỉ dùng một bộ chữ số đơn giản là hệ nhị phân, chỉ gồm hai chữ số 0 và 1. Các toán tử thao tác bit là các phép toán thực hiện với chữ số nhị phân. Tuy nhiên trong các ngôn ngữ cấp cao như Python chúng ta cũng ít khi dùng đến chúng.
KÍ HIỆU | Ý NGHĨA |
---|---|
~ |
Phép nghịch đảo |
^ |
Phép xor |
& |
Phép and |
| |
Phép or |
<< |
Phép dịch trái |
>> |
Phép dịch phải |
Phép nghịch đảo có tác dụng đổi các bit từ 0 sang 1 và ngược lại.
>>> ~7 -8 >>> ~-8 7
Phép nghịch đảo của số 7 là -8. Nếu chúng ta thực hiện nghịch đảo của -8 sẽ lại được 7.
Toán tử and
so sánh 2 bit với nhau, kết quả là 1 nếu cả hai là 1, ngược lại thì ra 0.
00110 & 00011 = 00010
>>> 6 & 3 2 >>> 3 & 6 2
Toán tử or
so sánh 2 bit với nhau. Nếu một trong hai bit là 1 thì kết quả sẽ ra 1. Nếu cả 2 là 0 thì kết quả ra 0.
00110 | 00011 = 00111
Kết quả của phép toán trên là 00110
hay số 7 trong hệ 10.
>>> 6 | 3 7
Phép toán xor
so sánh 2 bit. Nếu cả 2 giống nhau thì ra 0, ngược lại thì ra 1.
00110 ^ 00011 = 00101
Kết quả trên ra 00101
hoặc 5 trong hệ 10.
>>> 6 ^ 3 5
TIếp theo là các toán tử dịch bit. Chúng ta có phép dịch bit sang trái và sang phải. Ví dụ với dãy bit 00110
khi dịch sang trái sẽ được 01100
, còn dịch sang phải sẽ được 00011
. Phép dịch bit sang trái còn mang ý nghĩa là nhân một số cho 2, còn dịch sang phải mang ý nghĩa chia một số cho 2.
00110 >> 00001 = 00011
Trong ví dụ trên, chúng ta có 00110
là số 6 trong hệ 10, khi dịch dang phải 1 bit, chúng ta được dãy bit 00011
hay 3 trong hệ 10. Tức là chúng ta đã chia 6 cho 2 và được 3.
>>> 6 >> 1 3
00110 << 00001 = 01100
Ngược lại cũng với dãy bit 00110
khi dịch trái chúng ta được 01100
tức 12 trong hệ 10. Tức là chúng ta đã nhân 6 cho 2 và được 12.
>>> 6 << 1 12
Toán tử gán bằng
Các toán tử gán bằng bao gồm 2 kí tự, thực chất chúng chỉ là cách viết tắt thôi.
>>> i = 1 >>> i = i + 1 >>> i 2 >>> i += 1 >>> i 3
Toán tử +=
là một toán tử gán bằng. Ví dụ i += 1
tương đương với i = i + 1.
Cách viết này rất được hay dùng.
Dưới đây là một số toán tử gán bằng khác:
-= *= /= //= %= **= &= |= ^= >>= <<=
Mức độ ưu tiên của toán tử
Khi một biểu thức có nhiều toán tử, chúng sẽ được thực hiện từ các toán tử có độ ưu tiên cao hơn đến thấp hơn.
Ví dụ với biểu thức dưới đây, phép toán * sẽ được thực hiện trước rồi mới đến phép toán +.
3 + 5 * 5
Cũng giống như trong toán, chúng ta có thể tăng mức độ ưu tiên cho một toán tử bằng cặp dấu ().
(3 + 5) * 5
Các toán tử nằm trong cặp dấu ()
sẽ được ưu tiên thực hiện trước.
Dưới đây là danh sách các toán tử được sắp xếp theo mức độ ưu tiên từ cao xuống thấp.
unary + - ~ ** * / % + - >> << & ^ | < <= == >= > != <> is not and or
Các toán tử nằm cùng hàng với nhau có mức độ ưu tiên bằng nhau, khi đó chúng sẽ được thực hiện từ trái qua phải.
print (3 + 5 * 5) print ((3 + 5) * 5) print (2 ** 3 * 5) print (not True or True) print (not (True or True))
Đoạn code trên ví dụ về mức độ ưu tiên của một số toán tử.
print (2 ** 3 * 5)
Phép lấy lũy thừa có mức độ ưu tiên cao hơn phép nhân. Do đó phép tính 2 ** 3
sẽ được thực hiện trước rồi mới nhân cho 5. Kết quả ra 40.
print (not True or True)
Trong dòng trên, toán tử not
có độ ưu tiên cao hơn nên sẽ được thực hiện trước sau đó mới đến toán tử or. Kết quả ra True.
28 40 40 True False
Các toán tử quan hệ có mức độ ưu tiên cao hơn toán tử boolean.
a = 1 b = 2 if (a > 0 and b > 0): print ("a and b are positive integers")
Trong đoạn code trên, toán tử and
sẽ được thực hiện sau cùng khi 2 toán tử quan hệ đã thực hiện xong.
a and b are positive integers