2.5. Phương thức chuỗi và định dạng

Chuỗi đi kèm với một hộp công cụ các phương thức tích hợp để kiểm tra và định hình lại. Vì chuỗi là bất biến, mọi phương thức đều trả về một chuỗi mới -- chuỗi gốc không thay đổi.

2.5.1. Kiểm tra chuỗi

  • str.startswith() / str.endswith() -- kiểm tra tiền tố hoặc hậu tố; trả về bool.

  • str.find() -- vị trí của lần xuất hiện đầu tiên của một chuỗi con, hoặc -1 nếu không có. str.index() làm điều tương tự nhưng gây ra ValueError khi không tìm thấy.

  • str.count() -- số lần xuất hiện không chồng lấp.

  • Từ khóa in -- "MV" in name trả về True nếu chuỗi con có ở bất kỳ đâu trong chuỗi.

>>> name = "OpenMV Cam"
>>> name.startswith("Open")
True
>>> name.find("MV")
4
>>> name.count("m")
1
>>> "Cam" in name
True

2.5.2. Làm sạch và chuyển đổi chữ hoa/thường

  • str.strip() -- xóa khoảng trắng ở đầu và cuối. Truyền một chuỗi ký tự để xóa một tập tùy chỉnh (s.strip("/")).

  • str.lower() / str.upper() -- chuyển đổi chữ hoa/thường.

  • str.replace() -- thay thế chuỗi con.

>>> "  hello  ".strip()
'hello'
>>> "abc-123".replace("-", "_")
'abc_123'
>>> "OpenMV".lower()
'openmv'

2.5.3. Tách và nối

  • str.split() -- tách một chuỗi thành danh sách tại mỗi lần xuất hiện của dấu phân cách (mặc định: bất kỳ chuỗi khoảng trắng nào).

  • str.join() -- ngược lại: ghép một dãy chuỗi lại với nhau dùng chuỗi nhận như dấu phân cách. Đây là cách hiệu quả để xây dựng một chuỗi dài từ các mảnh.

>>> "1,2,3".split(",")
['1', '2', '3']
>>> "hello world".split()
['hello', 'world']
>>> ", ".join(["a", "b", "c"])
'a, b, c'

2.5.4. f-string

Cách đơn giản nhất để nội suy giá trị vào một chuỗi là f-string -- một chuỗi literal có tiền tố f. Bất kỳ biểu thức nào bên trong {} đều được đánh giá và chèn vào:

>>> name = "OpenMV"
>>> count = 42
>>> f"{name} saw {count} blobs"
'OpenMV saw 42 blobs'

Dấu hai chấm bên trong dấu ngoặc nhọn giới thiệu một đặc tả định dạng kiểm soát cách giá trị được hiển thị:

  • {x:.2f} -- số thực với 2 chữ số sau dấu thập phân.

  • {x:>10} -- căn phải trong trường 10 ký tự.

  • {x:<10} -- căn trái.

  • {x:0>4} -- đệm với các số không ở đầu đến độ rộng 4.

  • {x:#x} -- biểu diễn thập lục phân với tiền tố 0x.

  • {x:b} -- biểu diễn nhị phân.

>>> f"pi is roughly {3.14159:.3f}"
'pi is roughly 3.142'
>>> f"reg = {0xAB:#x}"
'reg = 0xab'
>>> for i in range(3):
...     print(f"line {i:0>3}")
line 000
line 001
line 002

Một = đơn sau tên biểu thức in cả tên và giá trị -- hữu ích để debug nhanh:

>>> v = 3.14
>>> print(f"{v=}")
v=3.14

2.5.4.1. Chuyển đổi cơ số nguyên

Ba hàm dựng sẵn làm cùng công việc như đặc tả định dạng :b / :o / :x nhưng trả về chuỗi đã chuyển đổi trực tiếp:

  • bin() -- cơ số 2, với tiền tố "0b".

  • oct() -- cơ số 8, với tiền tố "0o".

  • hex() -- cơ số 16, với tiền tố "0x".

>>> hex(255)
'0xff'
>>> bin(10)
'0b1010'
>>> oct(8)
'0o10'

Chiều ngược lại -- chuyển một chuỗi cơ số N trở lại thành số nguyên -- sử dụng constructor int với một cơ số tường minh:

>>> int("ff", 16)
255
>>> int("0b1010", 2)         # the "0b" prefix is allowed
10

Dùng các hàm này khi bạn muốn chuỗi thô cho một số nguyên (cho một dòng log, một tệp cấu hình, một dump thanh ghi). Dùng đặc tả định dạng khi bạn muốn đệm, độ rộng, hoặc trộn giá trị với văn bản khác trong cùng một f-string.

2.5.5. Các kiểu định dạng cũ hơn

f-string là kiểu được khuyến nghị, nhưng hai cách tiếp cận cũ hơn vẫn hoạt động và xuất hiện trong code hiện có:

str.format() -- dấu ngoặc nhọn với các đối số vị trí hoặc từ khóa được truyền vào phương thức .format() trên một chuỗi mẫu:

>>> "Hello, {}".format(name)
'Hello, OpenMV'
>>> "{0} + {0} = {1}".format(2, 4)
'2 + 2 = 4'
>>> "{name}: {value}".format(name="frames", value=42)
'frames: 42'

Các đặc tả định dạng ({:.2f}, {:>10}, ...) hoạt động giống như trong f-string; sự khác biệt duy nhất là nơi giá trị được cung cấp.

Định dạng % (kiểu printf) -- một toán tử % đơn thay thế các giá trị vào các mã định dạng, một giá trị cho mỗi mã. Truyền nhiều giá trị dưới dạng tuple:

>>> "Hello, %s" % name
'Hello, OpenMV'
>>> "%d + %d = %d" % (2, 2, 4)
'2 + 2 = 4'
>>> "%.2f" % 3.14159
'3.14'

Các mã kiểu phổ biến nhất là %s (chuỗi), %d (số nguyên), %f (số thực), và %x (hex).

Mỗi mã % có thể mang các bộ điều chỉnh giữa % và chữ cái kiểu. Hình dạng đầy đủ là %[flags][width][.precision]type:

  • width -- số ký tự tối thiểu mà trường phải chiếm. Các giá trị ngắn hơn được đệm với dấu cách; các giá trị dài hơn tràn ra. %10d dành 10 ký tự và căn phải số.

  • precision -- ý nghĩa phụ thuộc vào kiểu. Với số thực, là số chữ số sau dấu thập phân. %.2f cho hai chữ số thập phân. Với chuỗi, là số ký tự tối đa để lấy (%.5s cắt xuống năm ký tự).

  • Căn trái -- cờ - đặt trường ở bên trái. %-10d đặt các chữ số ở bên trái với dấu cách ở cuối.

  • Đệm số không -- cờ 0 đệm với các số không ở đầu thay vì dấu cách (cho kiểu số). %05d đệm số không đến năm chữ số.

  • Dấu -- cờ + luôn hiển thị dấu trên các số, bao gồm + cho số dương.

  • Dạng thay thế -- cờ #. Với %x thì thêm tiền tố 0x vào đầu ra; với %o thì thêm 0o.

Các cờ, độ rộng và độ chính xác có thể được kết hợp:

>>> "%10d" % 42
'        42'                 # width 10, space-padded, right-aligned
>>> "%-10d|" % 42
'42        |'                # width 10, left-aligned
>>> "%05d" % 42
'00042'                      # width 5, zero-padded
>>> "%8.2f" % 3.14159
'    3.14'                   # width 8, 2 decimal places
>>> "%08.2f" % 3.14159
'00003.14'                   # width 8, zero-padded
>>> "%+d" % 42
'+42'                        # explicit sign
>>> "%#06x" % 0xAB
'0x00ab'                     # 0x prefix, zero-pad to 6 chars total

Cả hai kiểu cũ hơn đều chậm hơn để đọc và dễ gây lỗi hơn f-string -- hãy dùng f-string trong code mới, và nhận ra các dạng cũ hơn khi đọc code hiện có.