2017-01-13 17 views
33

Tôi thực sự tò mò về :s chuỗi định dạng bằng Python 3. The documentation nói !schuyển đổi:sformat_spec.Sử dụng s vs: s để định dạng một chuỗi bằng Python

Nó cũng cho biết !s sẽ áp dụng str(), nhưng nó không nói bất cứ điều gì tương tự về :s. Tôi nghĩ rằng không có sự khác biệt đáng kể giữa họ, nhưng tôi muốn chắc chắn. Bất cứ ai có thể làm rõ những?

Một số mã ví dụ:

print("{!s}".format("this")) 
print("{:s}".format("that")) 
# I want to be sure that these two are processed identically internally 

Nó vẫn còn khó hiểu, nhưng hãy để tôi quấn lên với những lời của riêng tôi (cư sĩ của).

  1. type("whatever".format) luôn là str.
  2. Sử dụng !s nếu bạn muốn chuyển đổi đối tượng thành str trước khi định dạng.
  3. :s có nghĩa là đối tượng (hoặc đối tượng được chuyển đổi) sẽ được coi là str trong một số quy trình định dạng nội bộ. Đó là mặc định format_spec.

Có gì sai ở đây không?

Trả lời

30

!s, và anh em của nó !a!r áp dụng str(), ascii()repr() tương ứng trước suy và định dạng. Chúng được gọi là cờ chuyển đổi, và là một phần của Format String Syntax spec, không phải là per-field formatting spec áp dụng cho giá trị khi nội suy:

Các chuyển đổi lĩnh vực gây ra một kiểu ép buộc trước khi định dạng. Thông thường, công việc định dạng một giá trị được thực hiện theo phương thức __format__() của chính giá trị đó. Tuy nhiên, trong một số trường hợp, việc ép buộc một kiểu được định dạng thành chuỗi là bắt buộc, sẽ ghi đè định nghĩa định dạng của riêng nó. Bằng cách chuyển đổi giá trị thành chuỗi trước khi gọi __format__(), logic định dạng thông thường bị bỏ qua.

Mỏ nhấn mạnh đậm.

:s chỉ áp dụng sau đó cho kết quả chuyển đổi (hoặc đối tượng gốc nếu không có chuyển đổi nào được áp dụng) và chỉ khi phương thức __format__ cho loại đối tượng hỗ trợ tùy chọn định dạng đó. Thông thường, chỉ các đối tượng thuộc loại str mới hỗ trợ trình định dạng này; nó có ở dạng mặc định, chủ yếu là vì Format Specification Mini-Language cho phép sự tồn tại của một ký tự loại và vì cũ hơn %printf-style formatting có định dạng %s. Nếu bạn đã cố gắng áp dụng loại s cho một đối tượng không hỗ trợ nó, bạn sẽ nhận được một ngoại lệ.

Sử dụng !s (hoặc !a hoặc !r) khi bạn có một đối tượng đó không phải là bản thân một chuỗi và một trong hai không hỗ trợ định dạng khác (không phải tất cả các loại làm) hoặc sẽ định dạng khác so với họ str(), ascii() hoặc repr() chuyển đổi:

>>> class Foo: 
...  def __str__(self): 
...   return "Foo as a string" 
...  def __repr__(self): 
...   return "<Foo as repr, with åéæ some non-ASCII>" 
...  def __format__(self, spec): 
...   return "Foo formatted to {!r} spec".format(spec) 
... 
>>> print("""\ 
... Different conversions applied: 
... !s: {0!s:>60s} 
... !r: {0!r:>60s} 
... !a: {0!a:>60s} 
... No conversions: {0:>50s} 
... """.format(Foo())) 
Different conversions applied: 
!s:         Foo as a string 
!r:    <Foo as repr, with åéæ some non-ASCII> 
!a: <Foo as repr, with \xe5\xe9\xe6 some non-ASCII> 
No conversions: Foo formatted to '>50s' spec 

Lưu ý: tất cả các định dạng được theo quy định của spec định dạng này thuộc trách nhiệm của phương pháp __format__; dòng cuối cùng không áp dụng thao tác căn chỉnh trong thông số định dạng >50s, phương pháp Foo.__format__ chỉ sử dụng phương thức này làm văn bản chữ trong thao tác định dạng (sử dụng chuyển đổi !r tại đây). Mặt khác, đối với các giá trị được chuyển đổi, phương pháp str.__format__ được sử dụng và đầu ra được căn chỉnh ở bên phải trong trường rộng 50 ký tự, được đệm bằng dấu cách ở bên trái.

-1

Từ các tài liệu, Python String Formatting:

Các field_name được tùy chọn theo sau là một lĩnh vực chuyển đổi, được bắt đầu bằng một dấu chấm than, và một format_spec, được đi trước bởi một dấu hai chấm ' '!' : '.

Vì vậy, không, nó không giống nhau.

Ví dụ:

Nếu bạn muốn in phao dạng chuỗi, bạn cần chuyển đổi (dấu phẩy → chuỗi).

"{!s}".format(2.1457) 
>>> 2.1457 
type("{!s}".format(2.1457)) 
>>> <type 'str'> 

Nếu bạn không sử dụng dấu chuyển đổi, bạn sẽ gặp lỗi.

"{:s}".format(2.1457) 
>>> ValueError: Unknown format code 's' for object of type 'float' 
+0

"Trường chuyển đổi" tự nói lên. – iFlo

+2

'" .. ". Định dạng (..)' là ** luôn luôn ** một chuỗi. Bản demo 'type()' của bạn có ý nghĩa rất ít trong ngữ cảnh này, vì nó sẽ * luôn luôn giống nhau * bất kể thông số định dạng hoặc chuyển đổi nào đã được áp dụng cho các đối tượng đã định dạng. –

+0

Ngoài ra, còn có các loại thông số định dạng khác sẽ tăng ngoại lệ, ngay cả khi bạn áp dụng chuyển đổi '! S', như' i'. –

2

Bạn không may là bạn đã sử dụng chuỗi làm giá trị cần định dạng. Sử dụng khá nhiều đối tượng khác mà bạn muốn có được cách chúng không giống nhau.

In (càng nhiều càng tốt tôi có thể) layman ngữ:

  • Sự vắng mặt hay sự tồn tại của lá cờ chuyển đổi định loại giá trị chúng ta sẽ định dạng và, bởi mức độ, ai là __format__ chúng tôi sẽ gọi. Như Martjin đã chỉ ra, bằng cách sử dụng điều này, chúng ta có thể bỏ qua hành vi nào đó và xử lý giá trị tổng quát hơn (giống như một chuỗi). Nó có ba hương vị khác nhau tương ứng với ba cách khác nhau mà một đối tượng có thể chọn để thể hiện chính nó như là một chuỗi.
  • Trình chỉ định loại, cùng với các thông số khác, chỉ định cách loại chúng tôi có cuối cùng sẽ được hiển thị. Đối với các chuỗi không có tập hợp các tùy chọn phong phú (một chuỗi được trình bày như cũ) nhưng đối với các loại như int s, bạn có thể có các bản trình bày khác nhau.

Tôi nghĩ, mặc dù, rằng type có lẽ là một tên khó hiểu để cung cấp thông số này.

Các vấn đề liên quan