Bạn đã có câu trả lời, nhưng chỉ muốn thêm vào, không phải tất cả các dấu chấm câu đều bị mắc kẹt ở phía bên tay trái. Nếu bạn muốn giải quyết các câu tổng quát hơn, bạn có thể có ví dụ như dấu ngoặc đơn hoặc dấu nháy đơn và bạn không muốn kết thúc bằng một cái gì đó như:
Đó là một bộ phim tuyệt vời (tốt nhất tôi đã xem)
Tôi muốn nói thật vô nghĩa khi tạo ra một số lớp lót khó chịu, chỉ để thực hiện điều này theo cách đa chiều nhất. Nếu bạn không cần giải pháp siêu nhanh, bạn có thể xem xét giải quyết nó bước-by-step, ví dụ:
import re
s = ['It', "'", 's', 'a', 'great', 'movie',
'(', 'best', 'I', "'", 've', 'seen', ')']
s = " ".join(s) # join normally
s = re.sub(" ([,.;\)])", lambda m: m.group(1), s) # stick to left
s = re.sub("([\(]) ", lambda m: m.group(1), s) # stick to right
s = re.sub(" ([']) ", lambda m: m.group(1), s) # join both sides
print s # It's a great movie (best I've seen)
Nó khá linh hoạt và bạn có thể xác định những dấu chấm câu được xử lý bởi từng quy tắc ... Nó có 4 dòng mặc dù, vì vậy bạn có thể không thích nó. Bất kể bạn chọn phương pháp nào, có thể sẽ có một số câu không hoạt động chính xác và cần trường hợp đặc biệt, vì vậy một lớp lót có thể chỉ là một lựa chọn tồi.
EDIT: Trên thực tế, bạn có thể ký hợp đồng giải pháp trên để một dòng, nhưng như đã nói trước đây, tôi khá chắc chắn rằng có nhiều trường hợp để xem xét:
print re.sub("([,.;\)]|[\(] | ['])", lambda m: m.group(1).strip(), " ".join(s))
Tốt hơn là không nên đặt tên biến "chuỗi" sau khi bạn vừa nhập mô-đun có cùng tên. Sau mã này, "chuỗi" có thể là biến kiểu str, không phải là mô-đun và điều này có thể gây nhầm lẫn cho những người thiếu kinh nghiệm. – MihanEntalpo