Trong bài các kiểu dữ liệu cơ bản chúng ta đã học về kiểu string, trong bài này chúng ta sẽ tìm hiểu sâu hơn về kiểu dữ liệu này. String là một trong những kiểu dữ liệu quan trọng trong các ngôn ngữ lập trình, vì thế nên mình quyết định dành hẳn một bài để nói về string.
Khởi tạo string
Trong Python, để tạo một string, chúng ta có thể dùng một dấu nháy đơn, một dấu nháy kép hoặc ba dấu nháy kép. Khi dùng ba dấu nháy kép, chúng ta có thể viết string trên nhiều dòng mà không cần dùng ký tự thoát.
a = "proximity alert" b = 'evacuation' c = """ requiem for a tower """ print (a) print (b) print (c)
Trong ví dụ trên, chúng ta khởi tạo 3 string và in ra màn hình.
proximity alert evacuation requiem for a tower
Dùng dấu nháy bên strong string
Để tạo string thì chúng ta dùng các dấu nháy, nhưng nếu chúng ta muốn dùng chính các dấu nháy đó bên trong string thì sao? Có hai cách, một là dùng kí tự thoát, hai là trộn lẫn giữa dấu nháy cần dùng với dấu nháy khởi tạo string.
print ("There are many stars.") print ("He said, \"Which one is your favourite?\"") print ('There are many stars.') print ('He said, "Which one is your favourite?"')
Cách thứ nhất là dùng kí tự thoát \ các kí tự điều khiển sẽ bị vô hiệu hóa và sẽ được in ra như các kí tự bình thường. Cách thứ hai là chúng ta trộn, nếu muốn sử dụng dấu nháy kép trong string thì chúng ta dùng dấu nháy đơn để bao bọc lấy string và ngược lại.
There are many stars. He said, "Which one is your favourite?" There are many stars. He said, "Which one is your favourite?"
Độ dài của string
Phương thức len()
trả về số lượng chữ cái trong string, kể cả dấu cách.
s1 = "Eagle" s2 = "Eagle\n" s3 = "Eagle " print (len(s1)) print (len(s2)) print (len(s3))
Ví dụ trên in ra độ dài của 3 string.
s1 = "Eagle" s2 = "Eagle\n" s3 = "Eagle "
Ở đây, string thứ 2 có kí tự xuống dòng, string thứ 3 có 2 dấu cách và chúng đều được tính.
5 6 7
Loại bỏ khoảng trắng thừa trong string
Đôi khi các khoảng trắng thừa ở đầu string hay cuối string nhìn khá là khó chịu và bạn muốn loại bỏ chúng đi. Python cung cấp các phương thức strip(), rstrip()
và lstrip()
để làm công việc này. Bản thân các phương thức này không loại bỏ các kí tự trong string gốc mà chúng sẽ copy string gốc sang một nơi khác, sau đó loại bỏ khoảng trắng ở các string này rồi trả string mới này cho chúng ta.
s = " Eagle " s2 = s.rstrip() s3 = s.lstrip() s4 = s.strip() print (s, len(s)) print (s2, len(s2)) print (s3, len(s3)) print (s4, len(s4))
Ở ví dụ trên, chúng ta áp dụng cả 3 phương thức trên vào string s
. String s
có 1 khoảng trắng thừa ở đâu câu và 2 khoảng trắng thừa ở cuối câu.
s2 = s.rstrip()
Phương thức rstrip()
loại bỏ khoảng trắng thừa ở cuối string.
s3 = s.lstrip()
Phương thức lstrip()
loại bỏ khoảng trắng thừa ở đầu string.
s4 = s.strip()
Phương thức strip()
loại bỏ khoảng trắng thừa ở cả đầu và cuối string.
Eagle 8 Eagle 6 Eagle 7 Eagle 5
Chúng ta in kết quả ra màn hình. Lưu ý là python tự động cách dòng các thành phần trong hàm print
.
Các ký tự thoát
Đây là các kí tự đặc biệt dùng để điều khiển string.
print ("Incompatible, it don't matter though\n'cos someone's bound to hear my cry") print ("Speak out if you do\nYou're not easy to find")
Kí tự \n
mang ý nghĩa xuống dòng, kí tự nào đứng đằng sau kí tự này sẽ tự động xuống dòng.
Incompatible, it don't matter though 'cos someone's bound to hear my cry Speak out if you do You're not easy to find
Tiếp theo là kí tự backspace \b
.
print ("Python\b\b\booo") # prints Pytooo
Kí tự này đưa con trỏ về trước 1 kí tự. Trong ví dụ trên, chúng ta có 3 kí tự \b nên con trỏ được đưa lùi về 3 kí tự nên 3 kí tự hon được thay thế bằng 3 kí tự ooo.
print ("Towering\tinferno") # prints Towering inferno
Kí tự \t
có tác dụng in ra một dấu tab.
Nếu chúng ta đưa r
vào trước dấu nháy. Các ký tự thoát trong string sẽ không được sử dụng và chúng sẽ được in ra như các kí tự bình thường.
print (r"Another world\n")
Another world\n
Ngoài ra Python còn nhiều kiểu kí tự thoát khác nữa, bạn có thể tham khảo tại đây.
So sánh string
Chúng ta có thể so sánh 2 string bằng các toán tử ==
, !=
… và kết quả trả về là một giá trị boolean.
print ("12" == "12") print ("17" == "9") print ("aa" == "ab") print ("abc" != "bce") print ("efg" != "efg")
Trong ví dụ trên, chúng ta so sánh 2 string.
print ("12" == "12")
Hai string trên bằng nhau, kết quả là True.
print ("aa" == "ab")
Hai string trên khác nhau, hai kí tự đầu tiên bằng nhau nhưng kí tự thứ hai khác nhau, trong đó kí tự a lớn hơn kí tự b. Kết quả trả về là False.
print ("abc" != "bce")
Hai string này khác nhau hoàn toàn. Kết quả trả về là True.
True False False True False
Truy xuất phần tử trong string
Cũng như tuple, list… chúng ta có thể truy xuất các phần tử trong string.
s = "Eagle" print (s[0]) print (s[4]) print (s[-1]) print (s[-2]) print ("****************") print (s[0:4]) print (s[1:3]) print (s[:])
Ở trên chúng ta truy xuất thông qua chỉ số.
print (s[0]) print (s[4])
Chỉ số ở đây được đánh số từ 0, nếu string có 5 kí tự thì chúng được đánh số từ 0..4.
print (s[-1]) print (s[-2])
Nếu chúng ta đưa vào chỉ số là số âm, chúng ta lấy được các phần tử từ cuối string.
print (s[0:4])
Chúng ta có thể đưa các phạm vi lấy từ đâu đến đâu vào để lấy một tập các phần tử chứ không chỉ lấy được các phần tử riêng biệt.
print (s[:])
Nếu chúng ta đưa vào chỉ số như phía trên thì sẽ lấy toàn bộ string.
E e e l **************** Eagl ag Eagle
Chúng ta có thể dùng vòng lặp để duyệt qua string.
s = "Pho Code" for i in s: print (i,)
Đoạn code trên in toàn bộ các phần tử trong string ra màn hình.
P h o C o d e
Tìm string con
Các phương thức find()
, rfind()
, index()
và rindex()
là các phương thức dùng để tìm string con. Kết quả trả về là vị trí của kí tự đầu tiên của string con được tìm thấy trong string cha. Phương thức find()
và index()
tìm từ đầu string, phương thức rfind()
và rindex()
tìm từ cuối string.
Sự khác nhau của 2 phương thức find()
và index()
là nếu không tìm thấy string con thì phương thức đầu tiên trả về -1, còn phương thức thứ 2 trả về một ValueError
exception. Exception là một khái niệm quan trọng và chúng ta sẽ tìm hiểu ở các bài cuối.
find(str, beg=0, end=len(string)) rfind(str, beg=0, end=len(string)) index(str, beg=0, end=len(string)) rindex(str, beg=0, end=len(string))
Trong đoạn code trên, các phương thức này nhận vào 3 tham số, tham số đầu tiên str
là string con cần tìm, tham số thứ 2 và thứ 3 là vị trí bắt đầu tìm và vị trí kết thúc để tìm trong string cha. Chúng ta có thể không đưa 2 tham số này vào và các phương thức trên sẽ mặc định tìm từ vị trí đầu tiên là 0 và vị trí cuối cùng là độ dài của string cha.
a = "I saw a wolf in the forest. A lone wolf." print (a.find("wolf")) print (a.find("wolf", 10, 20)) print (a.find("wolf", 15)) print (a.rfind("wolf"))
Trong ví dụ trên, chúng ta có một string và chúng ta thử tìm string con từ các khoảng vị trí khác nhau.
print (a.find("wolf"))
Dòng trên tìm vị trí xuất hiện đầu tiên của string “wolf”.
print (a.find("wolf", 10, 20))
Dòng trên tìm vị trí xuất hiện đầu tiên của string “wolf” từ vị trí 10 đến 20 trong string gốc, kết quả trả về -1 vì không tìm thấy.
print (a.find("wolf", 15))
Dòng trên chúng ta cũng tìm string “wolf” từ vị trí 15 đến cuối string và tìm ra vị trí thứ hai mà string này xuất hiện trong string cha.
print (a.rfind("wolf"))
Phương thức rfind()
tìm string gốc từ cuối string cha, do đó cũng tìm ra vị trí thứ hai của string này trong string cha.
8 -1 35 35
Tiếp theo chúng ta sẽ tìm hiểu về phương thức index()
.
a = "I saw a wolf in the forest. A lone wolf." print (a.index("wolf")) print (a.rindex("wolf")) try: print (a.rindex("fox")) except ValueError as e: print ("Could not find substring")
Như đã nói ở trên, điểm khác nhau của phương thức này với phương thức find()
là cách chúng gửi giá trị trả về khi không tìm thấy.
print (a.index("wolf")) print (a.rindex("wolf"))
Hai dòng trên tìm vị trí bắt đầu của string “wolf” từ vị trí đầu và cuối string cha.
try: print (a.rindex("fox")) except ValueError as e: print ("Could not find substring")
Ở đây chúng ta thử tìm string “fox” và tất nhiên là không tìm thấy, phương thức này trả về một ValueError
exception.
8 35 Could not find substring
Toán tử trên string
Ví dụ dưới đây sử dụng toán tử nhân * và toán tử nối chuỗi.
print ("eagle " * 5) print ("eagle " "falcon") print ("eagle " + "and " + "falcon")
Toán tử * sẽ lặp lại string n
lần. Trong ví dụ trên là 5 lần. Hai string được đặt sát nhau sẽ tự động ngầm nối vào nhau. Bạn cũng có thể dùng dấu + để nối chuỗi một cách rõ ràng.
eagle eagle eagle eagle eagle eagle falcon eagle and falcon
Phương thức len()
có tác dụng tính số chữ cái trong string.
var = 'eagle' print (var, "has", len(var), "characters")
Ví dụ trên tính số lượng các kí tự có trong string.
eagle has 5 characters
Trong một số ngôn ngữ khác như Java, C#, kiểu string và kiểu số có thể được ngầm nối thành một string, chẳng hạn trong Java, bạn có thể gõ System.out.println("Number: " + 12)
để in chuỗi “Number: 12” ra màn hình. Python không cho phép điều này, bạn phải chuyển đổi kiểu dữ liệu một cách rõ ràng.
print (int("12") + 12) print ("There are " + str(22) + " oranges.") print (float('22.33') + 22.55)
Chúng ta có thể dùng phương thức int()
để chuyển một string thành một số, float()
để chuyển một string thành một số thực, hoặc hàm str()
để chuyển một số thành một string,
Thay thế string
Phương thức replace()
sẽ thay thế một chuỗi con trong chuỗi cha thành một chuỗi mới.
replace(old, new [, max])
Mặc định thì phương thức này sẽ thay thế tất cả các chuỗi con mà nó tìm thấy được. Nhưng bạn cũng có thể giới hạn phạm vi tìm kiếm.
a = "I saw a wolf in the forest. A lonely wolf." b = a.replace("wolf", "fox") print (b) c = a.replace("wolf", "fox", 1) print (c)
Ở ví dụ trên chúng ta thay thế string “wolf” thành “fox”.
b = a.replace("wolf", "fox")
Dòng trên sẽ thay thế tất cả các string “wolf” thành “fox”.
c = a.replace("wolf", "fox", 1)
Dòng này thì chỉ thay thế string “wolf” đầu tiên mà nó tìm thấy.
I saw a fox in the forest. A lonely fox. I saw a fox in the forest. A lonely wolf.
Tách, nối string
Chúng ta có thể tách một string bằng phương thức split()
hoặc rsplit()
. Kết quả trả về là một đối tượng kiểu list có các phần tử là các kí tự được tách ra từ string gốc, string gốc được tách dựa trên các kí tự phân cách mà chúng ta cung cấp. Ngoài ra 2 phương thức trên còn có 1 tham số thứ 2 là số lượng lần tách tối đa.
nums = "1,5,6,8,2,3,1,9" k = nums.split(",") print (k) l = nums.split(",", 5) print (l) m = nums.rsplit(",", 3) print (m)
Trong ví dụ trên, chúng ta sử dụng kí tự phân cách là dấu phẩy “,” để tách string thành các string con.
k = nums.split(",")
String gốc của chúng ta có 8 kí tự, nên list trả về sẽ có 8 phần tử.
l = nums.split(",", 5)
Dòng code trên quy định số lần tách tối đa là 5 lần, do đó list trả về của chúng ta sẽ có 6 phần tử.
m = nums.rsplit(",", 3)
Ở đây chúng ta tách string gốc thành 4 phần tử nhưng quá trình tách bắt đầu từ cuối string.
['1', '5', '6', '8', '2', '3', '1', '9'] ['1', '5', '6', '8', '2', '3,1,9'] ['1,5,6,8,2', '3', '1', '9']
Chúng ta có thể nối các string bằng hàm join()
. Các string được nối lại cũng có thể có các kí tự phân tách.
nums = "1,5,6,8,2,3,1,9" n = nums.split(",") print (n) m = ':'.join(n) print (m)
Trong ví dụ trên chúng ta tách string nums
ra dựa trên dấu phẩy “,”, sau đó nối các phần tử mới trong list n
thành một string và cách nhau bởi dấu hai chấm “:”.
m = ':'.join(n)
Phương thức join()
sẽ tạo ra một string mới từ một list các string con, cách nhau bởi dấu “:”.
['1', '5', '6', '8', '2', '3', '1', '9'] 1:5:6:8:2:3:1:9
Ngoài phương thức split()
dùng để tách chuỗi, chúng ta có một phương thức khác có chức năng tương tự là partition(),
phương thức này chỉ cắt chuỗi 1 lần khi nó gặp kí tự phân cách, do đó nó cũng giống như là khi dùng split(str, 1)
vậy. Thế nên kết quả trả về của phương thức này luôn là một list chứa 3 phần tử, phần tử đầu tiên là đoạn string nằm phía trước kí tự phân tách, phần tử thứ 2 là chính bản thân kí tự phân tách, phần tử thứ 3 là đoạn string nằm phía sau kí tự phân tách.
s = "1 + 2 + 3 = 6" a = s.partition("=") print (a)
Đoạn code trên ví dụ về phương thức partition()
.
a = s.partition("=")
('1 + 2 + 3 ', '=', ' 6')
Chữ HOA và chữ thường
Python có các phương thức để làm việc với từng trường hợp.
a = "PhoCode" print (a.upper()) print (a.lower()) print (a.swapcase()) print (a.title())
Ví dụ trên sử dụng bốn phương thức.
print (a.upper())
Phương thức upper()
sẽ chuyển toàn bộ các kí tự trong string thành viết HOA.
print (a.lower())
Phương thức lower()
sẽ chuyển toàn bộ các kí tự trong string thành viết thường.
print (a.swapcase())
Phương thức swapcase()
đảo ngược kiểu HOA thành kiểu thường và ngược lại.
print (a.title())
Phương thức title()
sẽ viết HOA chữ cái đầu tiên, các chữ cái còn lại sẽ chuyển thành kiểu thường.
PHOCODE phocode pHOcODE Phocode
Một số thao tác khác trên string
sentence = "There are 22 apples" alphas = 0 digits = 0 spaces = 0 for i in sentence: if i.isalpha(): alphas += 1 if i.isdigit(): digits += 1 if i.isspace(): spaces += 1 print ("There are", len(sentence), "characters") print ("There are", alphas, "alphabetic characters") print ("There are", digits, "digits") print ("There are", spaces, "spaces")
Ở đây chúng ta sử dụng các phương thức isalpha(), isdigit(), isspace()
để xác định xem kí tự nào là chữ cái, chữ số hay dấu cách.
There are 19 characters There are 14 alphabetic characters There are 2 digits There are 3 spaces
Ví dụ dưới đây chúng ta sẽ căn chỉnh lề khi in string ra màn hình.
print ("Ajax Amsterdam" " - " + "Inter Milano " "2:3") print ("Real Madridi" " - " "AC Milano " "3:3") print ("Dortmund" " - " "Sparta Praha " "2:1")
Bạn đã biết là chúng ta có thể nối chuỗi bằng cách đặt hai chuỗi sát nhau hoặc dùng toán tử +.
Ajax Amsterdam - Inter Milano 2:3 Real Madridi - AC Milano 3:3 Dortmund - Sparta Praha 2:1
Chúng ta sẽ căn chỉnh lề cho đẹp hơn.
teams = { 0: ("Ajax Amsterdam", "Inter Milano"), 1: ("Real Madrid", "AC Milano"), 2: ("Dortmund", "Sparta Praha") } results = ("2:3", "3:3", "2:1") for i in teams: print (teams[i][0].ljust(16) + "-".ljust(5) + \ teams[i][1].ljust(16) + results[i].ljust(3))
Ở ví dụ trên chúng ta có một kiểu từ điển và một tuple. Phương thức ljust()
sẽ đưa các string về lề trái, phương thức rjust()
để đưa các string về lề phải. Chúng ta có thể quy định số lượng kí tự của mỗi string, nếu string không đủ số lượng thì các dấu cách sẽ tự động được thêm vào.
Ajax Amsterdam - Inter Milano 2:3 Real Madrid - AC Milano 3:3 Dortmund - Sparta Praha 2:1
Định dạng string
Định dạng chuỗi tức là bạn đưa các tham số/biến vào bên trong string và tùy theo các tham số này mang giá trị gì mà string sẽ hiển thị ra giá trị đó. Định dạng kiểu này rất được hay dùng không chỉ trong Python mà các ngôn ngữ lập trình khác. Các tham số định dạng sử dụng toán tử %.
print ('There are %d oranges in the basket' % 32)
Ví dụ trên chúng ta sử dụng định dạng %d
, đây là định dạng cho số nguyên. Bên trong chuỗi, chúng ta ghi %d
tại vị trí mà chúng ta muốn hiển thị tham số, sau khi kết thúc chuỗi, chúng ta thêm % vào sau chuỗi và các giá trị và chúng ta muốn đưa vào.
There are 32 oranges in the basket
Nếu chúng ta dùng nhiều tham số bên trong chuỗi thì ở sau chuỗi các giá trị đưa vào phải nằm trong cặp dấu (),
tức là giống như một tuple vậy.
print ('There are %d oranges and %d apples in the basket' % (12, 23))
There are 12 oranges and 23 apples in the basket
Ví dụ dưới đây dùng tham số được định dạng kiểu số thực và kiểu string.
print ('Height: %f %s' % (172.3, 'cm'))
%f
dùng cho số thực, còn %s
là một string.
Height: 172.300000 cm
Mặc định định dạng số thực có 6 chữ số thập phân theo sau. Chúng ta có thể quy định số lượng chữ số này.
print ('Height: %.1f %s' % (172.3, 'cm'))
Bằng cách thêm dấu . và số phần thập phân vào giữa %
và f.
Python sẽ tự động loại bỏ các chữ số 0 thừa cho chúng ta.
Height: 172.3 cm
Dưới đây là một số kiểu định dạng khác.
# hexadecimal print ("%x" % 300) print ("%#x" % 300) # octal print ("%o" % 300) # scientific print ("%e" % 300000)
%x
sẽ chuyển một số từ hệ bất kì sang hệ thập lục phân, nếu thêm kí tự # vào giữa %x thì được thêm cặp chữ 0x
😀 Định dạng %o
là hiển thị số ở hệ bát phân (octal). %e
thì hiển thị theo định dạng số mũ (thật ra mình cũng chẳng biết kiểu định dạng này 😀 )
12c 0x12c 454 3.000000e+05
Ví dụ dưới đây chúng ta sẽ in ra các chữ số trên 3 cột.
for x in range(1,11): print ('%d %d %d' % (x, x*x, x*x*x))
1 1 1 2 4 8 3 9 27 4 16 64 5 25 125 6 36 216 7 49 343 8 64 512 9 81 729 10 100 1000
Như bạn thấy, các cột không được đều nhau nhìn không đẹp. Chúng ta sẽ thêm các đặc tả độ rộng vào. Bạn xem ví dụ để biết cách làm.
for x in range(1,11): print ('%2d %03d %4d' % (x, x*x, x*x*x))
Nếu như chúng ta ghi là %2d thì sẽ có thêm một dấu cách vào cho đủ 2 kí tự, nếu ghi là 03 thì các số 0 sẽ được thêm vào cho đủ 3 kí tự…
1 001 1 2 004 8 3 009 27 4 016 64 5 025 125 6 036 216 7 049 343 8 064 512 9 081 729 10 100 1000