Python 3

String trong python

Đăng bởi - Ngày 21-04-2018

String là gì?

String là tập hợp 1 chuỗi các ký tự theo các bảng chữ cái, tùy vào ngôn ngữ từng quốc gia thì có số lượng ký tự khác nhau, trong tiếng anh thì có 26 chữ cái - 52 chữ cái nếu bạn đếm viết chữ cái viết hoa và viết thường riêng, và một số ký tự như !@#$%^&*()-=... Còn trong ngôn ngữ việt chúng ta có 29 chữ cái tất cả, 58 chữ cái viết hoa và viết thường...

Khi chúng ta nói tới văn bản thì mọi người thường hay nghĩ rằng đó là "chữ và những ký tự trên màn hình". Nhưng bạn đang lầm rồi, computers không xử chúng trong chữ và ký tự, mà xử lý chúng trong bit và byte. Mỗi một chữ trong văn bản mà bạn đang đọc trong bài này được chứa dưới dạng ký tự được mã hóa. Nói ngắn gọn thì những ký tự mã hóa này được kết nối giữa cái mà bạn đang thấy với những thứ được computer lưu trữ trong bộ nhớ và ổ đĩa. Và vì vậy, có rất nhiều dạng ký tự được mã hóa khác nhau theo các ngôn ngữ khác nhau như tiếng Việt, tiếng Nga, tiếng Nhật, tiếng Trung...

Ok, đọc dài dòng thế thôi nhưng bạn chỉ cần biết nó là chữ, và chữ đó thuộc ngôn ngữ bạn đọc được là được rồi :p

UTF-8 - Mã hóa trong python

Trong Python 3, tất cả các chuỗi là chuỗi ký tự unicode. Không có chuyện một chuỗi mã hóa UTF-8 và một chuỗi khác mã hóa với CP-1252. UTF-8 là cách mã hóa ký tự như một chuỗi các bytes, nên nếu bạn muốn chuyển đổi các bytes sang string hoặc ngược lại thì python đều có thể giúp bạn. Bạn cần nhớ rằng: Bytes là bytes, bytes không phải ký tự. Ký tự là trừu tượng, và string là một chuỗi các trừu tượng đó tạo thành

>>> chuoi = 'こんにちは Python' #1
>>> len(chuoi) #2
12
>>> chuoi[0] #3
'こ'
>>> chuoi + ' 3' #4
'こんにちは Python 3'
  1. Để tạo một string, bạn cần đặt nó trong dấu nháy. String có thể đặt trong nháy đơn (') hoặc nháy kép (").
  2. Function len() này mình đã dùng trong các bài trước, nó sẽ trả về độ dài của string, số ký tự trong string. len() có thể dùng cho list, tuple, set, dictionary. String có thể được xem là tuple của những ký tự
  3. Cũng giống như là bạn lấy các phần tử trong list, bạn có thể lấy ra một ký tự dựa trên vị trí index, bắt đầu từ 0
  4. Cũng như list, bạn có thể nối thêm chuỗi bằng dấu cộng "+"

Nối chuỗi cho string

Trong python 2 chúng ta có thể nối chuỗi cho string bằng cách dùng "+" hoặc "%". Trong python 3 bổ sung thêm một cách mới đó là dùng dấu ngoặc nhọn {}. Theo cá nhân mình thấy thì sử dụng cặp {} hiệu quả hơn là cách của python 2. Nhưng tùy trường hợp mà ta sẽ áp dụng cách nào

>>> lop = "con "
>>> dongvat = "meo"
>>> lop + dongvat #1
'con meo'
>>> "Đó bạn đây là %s gì? Đây là %s %s" % (lop, lop, dongvat)
'Đó bạn đây là con  gì? Đây là con  mèo'
>>> "Đố bạn đây là {} gì? Đây là {} {}".format(lop, lop, dongvat) #3
'Đố bạn đây là con  gì? Đây là con  mèo'
>>> "Đố bạn đây là {0} gì? Đây là {0} {1}".format(lop, dongvat) #4
'Đố bạn đây là con  gì? Đây là con  mèo'
>>> "Đó bạn đây là {0} gì? Đây là {0} {2}".format(lop, dongvat) #5
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: tuple index out of range
>>> "Đó bạn đây là {0} gì? Đây là {0} {0}".format(lop, dongvat)
'Đó bạn đây là con  gì? Đây là con  con '
  1. Nếu string của bạn quá ngắn thì bạn nên dùng dấu "+" để nối chuỗi cho gọn
  2. Đây là cách python 2 thêm vào string bằng cách tạo 1 tuple chứa 2 phần tử tương ứng với số %s trong string. Tuy nhiên cách này hơi phức tạp vì nếu bạn cần lặp lại phần tử "lop" trong string bao nhiêu lần, thì bạn phải gọi nó trong tuple bấy nhiêu lần
  3. Đây là cách thêm vào chuỗi mà python 3 bổ sung vào. Thay vì bạn gọi bằng %sthì bạn sẽ gọi cặp ngoặc {} trong chuỗi, sau đó bạn sẽ đặt các phần tử tương ứng vào method format. Tuy nhiên cách viết này cũng không khác gì cách viết của python 2
  4. Đây mới là cách mà dấu {} hoạt động hiệu quả. Bạn sẽ gọi index vào {} để thêm vào string, như vậy bạn chỉ cần 2 phần tử trong format và gọi lại bao nhiêu lần trong string cũng được. Index bắt đầu từ 0
  5. Bạn có thể không phải dùng hết số index theo phần tử trong format(). Nhưng bạn số index của bạn không được lớn hơn số phần tử trong format()

Một số định dạng string đặc biệt

>>> '{0:.1f}'.format(11.234) #1
'11.2'
>>> '{0:.2f}'.format(11.234) #2
'11.23'
>>> '{0:.1f}'.format(2) #3
'2.0'
>>> '{1:.2f}'.format(11.234) #4
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: tuple index out of range
>>> float('{1:.2f}'.format(11.234, 3.125)) #5
3.12
  1. Bạn sẽ thấy {0:.1f} ở ví dụ này. {0:.1f} có hai phần, {0} là số index của phần tử trong format, vậy còn :.1f là gì? Trong định dạng bằng "{}", dấu hai chấm ":" có nghĩa là bắt đầu định dạng đặc biệt. ".1" nghĩa là hiện một số sau dấu thập phân, "f" nghĩa là số điểm cố định (fixed-point number)
  2. Nếu bạn tăng lên ".2f", kết quả trả lại 2 số là 11.23
  3. Nếu số cần định dạng là một integer thì python sẽ tự thêm ".0" vào kết quả
  4. Như mình đã nói ở trên, số {1} là index của phần tử trong format nên python sẽ báo lỗi exception IndexError, vì trong format() chỉ có 1 phần tử
  5. Vì method format() trả về định dạng là string nên nếu bạn cần kết quả là float thì bạn phải dùng float() để chuyển đổi

Một số method string thường sử dụng

Bên cạnh method format(), string có một số method hữu ít khác

>>> doanvan = '''Hằng năm cứ vào cuối thu, #1
... lá ngoài đường rụng nhiều và
...  trên không có những đám mây bàng bạc,
...  lòng tôi lại nao nức những kỷ niệm hoang mang của buổi tựu trường.'''
>>> doanvan.splitlines() #2
['Hằng năm cứ vào cuối thu,', 'lá ngoài đường rụng nhiều và', ' trên không có những đám mây bàng bạc,', ' lòng tôi lại nao nức những kỷ niệm hoang mang của buổi tựu trường.']
>>> print(doanvan.lower()) #3
hằng năm cứ vào cuối thu,
lá ngoài đường rụng nhiều và
 trên không có những đám mây bàng bạc,
 lòng tôi lại nao nức những kỷ niệm hoang mang của buổi tựu trường.
>>> print(doanvan.lower().count('b')) #4
3
  1. Bạn có thể nhập nhiều dòng cho string trong python interactive shell bằng cách dùng ba dấu nháy đơn ('''), hoặc nháy kép ("""). Khi bạn bắt đầu string với (''') sau đó nhấn enter, interactive shell sẽ cho bạn nhập dòng tiếp theo. Khi bạn đóng chuỗi bằng (''') và nhấn enter, interactive shell sẽ kết thúc string
  2. Method splitlines() nhận một param string nhiều dòng và trả về kết quả là list của string với phần tử là mỗi một dòng của string.
  3. Method lower() sẽ chuyển tất cả chữ trong string thành viết thường. Ngược lại method upper() sẽ viết hoa tất cả.
  4. Method count() dùng đếm ký tự trong string, count() nhận vào một string và đếm xem trong string gốc có chứa bao nhiêu string cần đếm

Một method khác cũng rất hay dùng đó là split(), ví dụ như chúng ta có một danh sách các cặp key-value theo định dạng query string key1=value1&key2=value2, và bạn muốn chuyển nó thành {key1: value1, key2: value2}

>>> query = 'user=mstring&database=master&password=NahxIak=p'
>>> connection = query.split('&') #1
>>> connection
['user=mstring', 'database=master', 'password=NahxIak=p']
>>> parse_db = [v.split('=', 1) for v in connection if '=' in v] #2
>>> parse_db
[['user', 'mstring'], ['database', 'master'], ['password', 'NahxIak=p']]
>>> db_dict = dict(parse_db) #3
>>> db_dict
{'user': 'mstring', 'database': 'master', 'password': 'NahxIak=p'}
  1. Method split() nhận một param vào là một ký tự hoặc chuỗi ký tự bất kỳ, dựa param đó split() sẽ cắt thành list. Trong ví dụ này chúng ta cắt chuỗi với ký tự '&'.
  2. Bây giờ chúng ta có một list mới với định dạng là key, dấu = và sau đó là value. Trên ví dụ trên, chúng ta dùng list comprehension để chạy toàn bộ list sau đó chia mỗi string thành 2 string mới dựa theo dấu '='. Trong ví dụ bạn sẽ thấy trong method split() có param thứ 2. Param này là một optional, param thứ hai này cho phép chúng ta điều khiển được số lần mà split() sẽ chia ra, 1 nghĩa là chỉ chia ra 1 lần. Kết quả của split() sẽ trả về một list có hai phần tử. Chỗ này để nói rõ hiểu hơn thì bạn thấy string passwod có hai dấu '=', optional param 2 của method split() chỉ cắt ở dấu '=' đầu tiên, còn dấu '=' phía sau sẽ bỏ qua, nếu bạn không dùng param này thì split() sẽ cắt tất cả dấu '=' trong string
  3. Cuối cùng, python sẽ chuyển list có được sang dictionary dễ dàng bằng function dict()

Ví dụ trên trông giống như query parameters của url, nhưng nếu trong dự án của bạn mà cần phân tích url thì bạn không nên dùng cách này. Việc phân tích url phức tạp hơn nhiều, python có cung cấp cho bạn một module chuyên về phân tích url đó là urllib.parse.parse_qs() 

Cắt một string

Khi một string được tạo ra, bạn có thể lấy bất kỳ phần nào trong string như một string mới. Đây được gọi là cắt chuỗi (Slicing the string). Cách để cắt chuỗi cũng như là cách cắt list đã giới thiệu ở bài trước.

>>> loibaihat = 'Một bông Hồng em dành tặng Cô. Một bài ca hát riêng tặng Thầy.'
>>> loibaihat[5:25] #1
'ông Hồng em dành tặn'
>>> loibaihat[5:-5] #2
'ông Hồng em dành tặng Cô. Một bài ca hát riêng tặng '
>>> loibaihat[0:6] #3
'Một bô'
>>> loibaihat[:18] #4
'Một bông Hồng em d'
>>> loibaihat[18:] #5
'ành tặng Cô. Một bài ca hát riêng tặng Thầy.'
  1. Bạn có thể lấy ra một đoạn bất kỳ trong string bằng cách chỉ định hai index. Giá trị trả về là một string mới chứa tất cả các ký tự trong string theo sắp xếp, bắt đầu từ index cần cắt đầu tiên
  2. Cũng như list(), bạn có thể dùng index âm để cắt chuỗi
  3. Index của string bắt đầu từ 0, vì vậy loibaihat[0:6] sẽ trả về 6 ký tự đầu, bắt đầu từ loibaihat[0] và kết thúc ở loibaihat[5].
  4. Nếu bên trái của index cần cắt là 0, bạn có thể để trống nó, mặc định python sẽ hiểu là 0. Như ở ví dụ trên loibaihat[:18] có nghĩa là loibaihat[0:18]
  5. Tương tự thì nếu bên phải index cần cắt để trống có nghĩa là toàn bộ chuỗi. Ở ví dụ trên loibaihat[18:] tương đương với loibaihat[18:62]. Hơi khó để mình giải thích chỗ này một chút, string loibaihat có tất cả 62 ký tự thì trong 62 ký tự này, loibaihat[:18] trả về 18 ký tự và loibaihat[18:] trả về toàn bộ chuỗi trừ 18 ký tự đầu tiên ra. Nói gọn lại thì loibaihat[:n] sẽ trả về kết quả bắt đầu từ ký tự đầu tiên, và loibaihat[n:] sẽ trả tất cả, không quan tâm đến độ dài của chuỗi là bao nhiêu.

String và bytes

Như mình đã nói ở đầu bài này: Bytes là bytes, bytes không phải ký tự. Ký tự là trừu tượng, và một chuỗi các ký tự Unicode bất biến được gọi là string. Chuỗi ký tự bất biến này là những con số bắt đầu từ 0 và kết thúc là 255 được gọi là bytes object.

>>> by = b'chao \x65m' #1
>>> by
b'chao em'
>>> type(by) #2
<class 'bytes'>
>>> len(by) #3
7
>>> by += b'\xff' #4
>>> by
b'chao em\xff'
>>> len(by) #5
8
>>> by[0] #6
99
>>> by[0] = 102 #7
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'bytes' object does not support item assignment
  1. Để tạo một bytes object, bạn hãy dùng b'' (cú pháp "byte literal"). Mỗi một byte với byte literal có thể là ký tự ASCII hoặc được mã hóa bỡi số hex từ \x00 đến \xff (0-255)
  2. Kiểm tra loại của bytes object cho ra bytes
  3. Cũng như list() và string, bạn có thể lấy độ của bytes bằng function len()
  4. Toán tử "+" cũng có thể dùng cho bytes để nối giữa hai bytes object. Kết quả trả về là một bytes mới
  5. Ta nối 7 bytes với 1 byte sẽ cho ra một bytes mới là 8 bytes
  6. Cũng như list và string, ta có thể dùng index để lấy byte trong bytes object. Phần tử của string là string, phần tử của bytes là interger. Interger này giới hạn giữa 0-255
  7. Bytes object không thể thay đổi được, bạn không thể gán giá trị mới cho một byte chỉ định. Nếu bạn cần thay đổi giá trị của bytes, bạn có thể sử dụng cắt chuỗi, và toán tử cộng (cách dùng như với string) hoặc bạn chuyển đổi bytes object thành bytearray
>>> by = b'chao \x65m'
>>> barr = bytearray(by) #1
>>> barr
bytearray(b'chao em')
>>> len(barr) #2
7
>>> barr[0] = 102 #3
>>> barr
bytearray(b'fhao em')
  1. Để chuyển một bytes object thành một bytearray object, bạn hãy built-in function bytearray()
  2. Method len() cũng dùng được cho bytearray()
  3. Khi bạn chuyển bytes object sang bytearray object, bây giờ bạn đã có thể gán giá trị cho byte. Lưu ý giá trị được gán phải là integer từ 0-255

Lưu ý là bạn không thể kết hợp giữa bytes và string được

>>> by = b'a'
>>> s = 'buoi sang'
>>> by + s #1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can't concat str to bytes
>>> s.count(by) 2
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: must be str, not bytes
>>> s.count(by.decode('ascii')) #3
1
  1. Bạn không thể nối chuỗi giữa hai loại dữ liệu khác nhau.
  2. Bạn không thể dùng bytes để đếm trong string, bởi vì trong string không có bytes. String là chuỗi các ký tự.
  3. Khi bạn decode bytes bạn sẽ có thể dùng bytes trong string. Bởi vì methode decode() nhận vào giá trị và trả về một string, và string có medthod encode() để nhận ký tự vào và trả về bytes object. Trong ví dụ trên thì chúng ta chuyển đổi chuỗi bytes trong mã ASCII thành chuỗi của các ký tự.

Các thẻ
Bài viết liên quan
String trong python

Ngày 21 Tháng 4, 2018

Toán học trong Python - Boolean, float và integer

Ngày 19 Tháng 4, 2018

Giới thiệu về list

Ngày 09 Tháng 4, 2018

0 nhận xét

    Không có nhận xét nào

Nhận xét mới

bắt buộc

yu.kusanagi
Từ Anh Vũ
Hồ Chí Minh, Việt Nam

Xin chào, tôi tên Từ Anh Vũ và là 1 free lancer developer và ngôn ngữ code yêu thích của tôi là Python và PHP. Công việc chủ yếu là viết các module cho magento, magento2, wordpress, django, flask và các framework khác
Nếu bạn muốn trao đổi với tôi hoặc muốn thuê tôi làm việc cho dự án của bạn, hãy liên hệ với tôi

ĐĂNG KÝ NHẬN BÀI MỚI

Tweets gần đây
Tác giả
Feeds
RSS / Atom
-->

Đăng ký nhận bài viết mới tại hocpython.com?

Hãy đăng ký nhận bài viết mới tại hocpython.com để:

  • Không bỏ lỡ các bài tutorials mới tại hocpython.com!
  • Cập nhật các công nghệ mới trong python!

Chỉ cần điền email và họ tên của bạn và nhấn Đăng ký nhận tin!