Tại sao% s tốt hơn + cho nối?


88

Tôi hiểu rằng chúng ta nên sử dụng %sđể nối chuỗi chứ không phải +trong Python.

Tôi có thể làm bất cứ điều gì:

hello = "hello"
world = "world"

print hello + " " + world
print "%s %s" % (hello, world)
print "{} {}".format(hello, world)
print ' '.join([hello, world])

Nhưng tại sao tôi nên sử dụng bất cứ thứ gì khác ngoài +? Viết nhanh hơn bằng cách viết đơn giản +. Sau đó, nếu bạn nhìn vào chuỗi định dạng, bạn chỉ định các loại ví dụ %s%dvà như vậy. Tôi hiểu nó có thể tốt hơn để được rõ ràng về các loại.

Nhưng sau đó tôi đọc rằng +nên tránh sử dụng để ghép nối mặc dù nó dễ gõ hơn. Có một lý do rõ ràng rằng các chuỗi nên được nối theo một trong những cách khác?


29
Ai bảo bạn tốt hơn?
yannis

3
%skhông phải để nối, đó là một đặc tả chuyển đổi cho định dạng chuỗi có nguồn gốc từ C's printf(3). Có những trường hợp để sử dụng điều đó hoặc một toán tử ghép; mà bạn sử dụng nên dựa trên phán đoán của tình huống, không phải giáo điều. Việc viết mã dễ dàng như thế nào là hoàn toàn không liên quan vì bạn sẽ chỉ làm điều đó một lần.
Blrfl

Tôi đã tập trung lại câu hỏi để chỉ trăn (mặc dù tôi không phải là người trăn và vẫn có thể có trục trặc trong mã). Vui lòng đảm bảo rằng đây là câu hỏi bạn đang hỏi, thực hiện bất kỳ cập nhật thích hợp nào và xem xét hỏi một câu hỏi khác nếu bạn quan tâm đến C hoặc Java.

12
Và bây giờ chúng ta có các chuỗi f cao cấp ! print(f"{hello} {world}"), có khả năng đọc kết nối vì các biến được nhìn thấy nơi chúng xuất hiện trong chuỗi và nhanh hơn str.format.
Enrico Borba

Câu trả lời:


88
  1. Dễ đọc. Cú pháp chuỗi định dạng dễ đọc hơn, vì nó tách kiểu từ dữ liệu. Ngoài ra, trong Python, %scú pháp sẽ tự động ép buộc bất kỳ strloại không nào str; trong khi nối chỉ hoạt động với strvà bạn không thể nối strvới int.

  2. Hiệu suất. Trong Python strlà bất biến, do đó, chuỗi bên trái và bên phải phải được sao chép vào chuỗi mới cho mỗi cặp ghép. Nếu bạn ghép bốn chuỗi có độ dài 10, bạn sẽ sao chép (10 + 10) + ((10 + 10) +10) + (((10 + 10) +10) +10) = 90 ký tự, thay vì chỉ 40 ký tự nhân vật. Và mọi thứ trở nên tồi tệ hơn khi số lượng và kích thước của chuỗi tăng lên. Java tối ưu hóa trường hợp này một số lần bằng cách chuyển đổi chuỗi kết nối để sử dụng StringBuilder, nhưng CPython thì không.

  3. Đối với một số trường hợp sử dụng, thư viện ghi nhật ký cung cấp API sử dụng chuỗi định dạng để tạo chuỗi mục nhập nhật ký một cách lười biếng ( logging.info("blah: %s", 4)). Điều này rất tốt cho hiệu suất được cải thiện nếu thư viện ghi nhật ký quyết định rằng mục nhật ký hiện tại sẽ bị loại bỏ bởi bộ lọc nhật ký, do đó không cần định dạng chuỗi.


31
Bạn có nguồn khoa học hay kinh nghiệm nào cho # 1 không? Bởi vì tôi nghĩ rằng nó ít dễ đọc hơn nhiều (đặc biệt là với hơn 2 hoặc ba đối số)
Lovis

4
@ L.Möller: Tôi không chắc chắn loại nguồn nào bạn mong đợi từ cuối cùng là trải nghiệm chủ quan (dễ đọc), nhưng nếu bạn muốn lý luận của tôi: 1)% s yêu cầu thêm 2 ký tự cho mỗi giữ chỗ so với + yêu cầu tối thiểu là 4 (hoặc 8 nếu bạn theo PEP8, 13 nếu bạn ép buộc), 2)% s được đặt trong một chuỗi, do đó dễ dàng phân tích trực quan hơn, với +, bạn có nhiều phần chuyển động hơn: chuỗi đóng, toán tử, biến , toán tử, chuỗi mở, 3) tô màu cú pháp% s có một màu cho mỗi hàm: chuỗi và giữ chỗ, với + bạn nhận được ba màu: chuỗi, toán tử và tô màu biến.
Lie Ryan

4
@ L.Möller: 4) Tôi có tùy chọn đặt các chuỗi định dạng dài hơn vào một biến hoặc từ điển, ngoài việc định dạng cần phải được thực hiện, 5) chuỗi định dạng có thể được người dùng chỉ định từ tệp cấu hình, lệnh args hoặc cơ sở dữ liệu , điều tương tự không thể được nói với sự kết hợp. Nhưng vâng, tôi cũng sẽ không sử dụng% s khi tôi có nhiều hơn 4-5 thứ để nội suy, thay vào đó tôi sẽ sử dụng biến thể% (varname) hoặc "{foo}". Format () trong Python. Tôi nghĩ rằng các tên rõ ràng cải thiện khả năng đọc cho các chuỗi định dạng dài hơn với nhiều biến được nội suy.
Lie Ryan

2
Tôi không biết điều gì là "đúng", đó là lý do tại sao tôi hỏi bạn có bằng chứng không :-). Thực sự đồng ý với nhận xét thứ hai của bạn
Lovis

6
Tôi thấy # 2 là nghi ngờ - bạn có tài liệu chứng minh không? Tôi không quen thuộc lắm với Java, nhưng trong phép nối C # nhanh hơn phép nội suy chuỗi . Tôi hoàn toàn đồng ý với # 1 và thực sự dựa vào đó để quyết định khi nào nên sử dụng cái nào, nhưng bạn phải nhớ phép nội suy đòi hỏi một số lượng phân tích chuỗi và độ phức tạp trong đó việc nối không yêu cầu điều đó.
Jimmy Hoffa

48

Tôi có phải là người duy nhất đọc từ trái sang phải không?

Đối với tôi, sử dụng %sgiống như nghe người nói tiếng Đức, nơi tôi phải đợi cho đến khi kết thúc một câu rất dài để nghe động từ là gì.

Cái nào trong số này là rõ ràng hơn trong nháy mắt nhanh chóng?

"your %s is in the %s" % (object, location)

hoặc là

"your " + object + " is in the " + location  

17
Rõ ràng đây là chủ quan, vì tôi tìm thấy cái đầu tiên dễ đọc hơn - và dễ viết và chỉnh sửa hơn. Cái thứ hai xen kẽ văn bản với mã che khuất cả hai và thêm nhiễu. Ví dụ, rất dễ để có được khoảng trắng trong giây.
JacquesB

5
@JacquesB Tôi thực sự nghĩ rằng bộ não của bạn đã quá quen thuộc với định dạng này đến mức bạn ngay lập tức nhảy đến dấu ngoặc và đang thay thế các từ ngay lập tức. Về mặt kỹ thuật, nó không phải là đọc từ trái sang phải, nhưng điều đó hoàn toàn tốt. Tôi thấy tôi cũng làm điều đó, vì vậy, 1, dễ đọc hơn vì tôi biết tôi phải xử lý các vấn đề khoảng cách ngu ngốc trước và sau các trích dẫn trong lần thứ hai, và điều đó thực sự rất chậm.
Nelson

3
Sau nnhiều thập kỷ, tâm trí của tôi cũng hoạt động như vậy ;-) Nhưng tôi vẫn đứng trước câu trả lời của mình, thứ hai rõ ràng hơn và dễ đọc hơn, do đó để duy trì. Và điều đó trở nên rõ ràng hơn khi có nhiều tham số mà bạn có. Cuối cùng, nếu đó là một người đàn ông thể hiện, hãy đi với những gì bạn quen thuộc và thoải mái; nếu đó là một nỗ lực của nhóm, thực thi đánh giá tính nhất quán và mã; mọi người có thể quen với một trong hai.
Mawg

4
Cách thứ nhất là dễ đọc hơn đối với tôi vì nó có ít "hành trình" ở giữa câu. Mắt tôi dễ dàng liếc đến cuối cùng, đó là bộ não của tôi để phân tích các trích dẫn, khoảng trắng và điểm cộng thêm. Tất nhiên, bây giờ tôi rất thích các chuỗi định dạng Python 3.6 : f"your {object} is in the {location}".
Dustin Wyatt

8
Tôi cũng thấy khó đọc và viết hơn khi biến cần được bao quanh bằng chính dấu ngoặc kép. "your '" + object + "' is in the '" + location + "'"... Tôi thậm chí không chắc là mình có được điều đó ngay bây giờ không ...
Dustin Wyatt

12

Một ví dụ làm rõ đối số dễ đọc:

print 'id: ' + id + '; function: ' + function + '; method: ' + method + '; class: ' + class + ' -- total == ' + total

print 'id: %s; function: %s; method: %s; class: %s --total == %s' % \
   (id, function, method, class, total)

(Lưu ý rằng ví dụ thứ hai không chỉ dễ đọc hơn mà còn dễ chỉnh sửa hơn, bạn có thể thay đổi mẫu trên một dòng và danh sách các biến trên một dòng khác)

Một vấn đề khác là mã% s cũng chuyển đổi thành chuỗi, nếu không, bạn phải sử dụng lệnh gọi str () cũng khó đọc hơn mã% s.


1
Tôi không đồng ý với tuyên bố đầu tiên của bạn, nhưng chúng tôi có thể đồng ý khác nhau, tôi chỉ định đăng một câu trả lời dọc theo dòng thứ hai của bạn, vì vậy, upvote
Mawg

6

Sử dụng +nên không thể tránh được nói chung. Trong nhiều trường hợp là cách tiếp cận chính xác. Sử dụng %shoặc .join()chỉ thích hợp hơn trong các trường hợp cụ thể, và nó thường khá rõ ràng khi chúng là giải pháp tốt hơn.

Trong ví dụ của bạn, bạn đang nối ba chuỗi với nhau và ví dụ sử dụng +rõ ràng là đơn giản nhất và dễ đọc nhất, và do đó được khuyến nghị.

%shoặc .format()hữu ích nếu bạn muốn nội suy chuỗi hoặc giá trị ở giữa chuỗi lớn hơn. Thí dụ:

print "Hello %s, welcome to the computer!" % name

Trong trường hợp này, việc sử dụng %snó dễ đọc hơn vì bạn tránh cắt chuỗi đầu tiên thành nhiều phân đoạn. Đặc biệt nếu bạn đang nội suy nhiều giá trị.

.join() là phù hợp nếu bạn có một chuỗi kích thước thay đổi của chuỗi và / hoặc bạn muốn nối nhiều chuỗi với cùng một dấu phân cách.


2

Vì thứ tự từ có thể thay đổi trong các ngôn ngữ khác nhau, nên biểu mẫu với %slà bắt buộc nếu bạn muốn hỗ trợ đúng cách dịch chuỗi trong phần mềm của bạn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.