Thay thế trần được đề cập bởi @steven-rumbalski sẽ là cách hiệu quả nhất để thực hiện việc này, nhưng không phải là cách duy nhất.
Đây là giải pháp khác sử dụng tính năng hiểu danh sách. Nếu văn bản đã được tách ra thành một danh sách các dòng, điều này sẽ nhanh hơn nhiều so với chạy join()
, replace()
và splitlines()
text = """A very very very very very very very very very very very very very very very very
long mutiline
string"""
lines = text.splitlines()
indented = [' ' + l for l in lines]
indented[0] = lines[0]
indented = '\n'.join(indented)
Danh sách này có thể được sửa đổi tại chỗ, nhưng có một chi phí hiệu suất đáng kể so với sử dụng một giây biến. Nó cũng nhanh hơn để thụt lề tất cả các dòng và sau đó hoán đổi dòng đầu tiên trong một thao tác khác.
Ngoài ra còn có mô-đun textwrap
. Tôi không đồng ý rằng việc sử dụng textwrap cho thụt đầu dòng là unpythonic. Nếu các dòng được nối trong một chuỗi chứa các dòng mới, chuỗi đó vốn đã được bao bọc. Thụt lề là một phần mở rộng hợp lý của gói văn bản, do đó, textwrap có ý nghĩa với tôi.
Ngoại trừ việc nó chậm. Thực sự, rất chậm. Giống như chậm hơn 15 lần.
Python 3 đã thêm indent
đến textwrap
làm cho thụt lề mà không cần gói lại rất dễ dàng. Có chắc chắn là một cách thanh lịch hơn để xử lý các vị từ lambda, nhưng điều này không chính xác những gì câu hỏi ban đầu đã được yêu cầu.
indented = textwrap.indent(text, ' ', lambda x: not text.splitlines()[0] in x)
Dưới đây là một số kết quả của các phương pháp khác nhau timeit
.
>>> timeit.timeit(r"text.replace('\n', '\n ')", setup='text = """%s"""' % text)
0.5123521030182019
Các giải pháp hiểu danh sách hai:
>>> timeit.timeit(r"indented = [' ' + i for i in lines]; indented[0] = lines[0]", setup='lines = """%s""".splitlines()' % text)
0.7037646849639714
>>> timeit.timeit(r"indented = [lines[0]] + [' ' + i for i in lines[1:]]", setup='lines = """%s""".splitlines()' % text)
1.0310905870283023
Và đây là những bất hạnh textwrap
kết quả:
>>> timeit.timeit(r"textwrap.indent(text, ' ', lambda x: not text.splitlines()[0] in x)", setup='import textwrap; text = """%s"""' % text)
7.7950868209591135
Tôi nghĩ một số thời điểm đó có thể là vị khủng khiếp không hiệu quả, nhưng ngay cả với đã bị xóa, textwrap.indent
vẫn chậm hơn 8 lần so với thay thế trần.
>>> timeit.timeit(r"textwrap.indent(text, ' ')", setup='import textwrap; text = """%s"""' % text)
4.266149697010405
Từ tài liệu cho 'next_indent':" Chuỗi sẽ được thêm vào tất cả các dòng đầu ra được bao bọc ". Vì không có gì đang được bọc, không có gì được thụt vào. –