2012-07-12 40 views
6

Đây là vấn đề tương tự như trong this question about floats.Định dạng chuỗi với “{0: d}” không chuyển đổi thành số nguyên

Khi bạn có một giá trị có thể được chuyển đổi thành số nguyên, số %d cũ sẽ chuyển đổi, nhưng định dạng thì không.

class MyIntegerTenClass: 
    def __int__(self): 
     return 10 
    def __str__(self): 
     return 'ten' 
ten = MyIntegerTenClass() 
print '%d, %02X, %s' % (ten, ten, ten) # ok 
print '{0}'.format(ten) # ok 
print '{0:d}, {0:02X}'.format(ten) # ValueError: Unknown format code 'd' for object of type 'str' 

Có cách nào để thay đổi hành vi của định dạng, mà không cần chạm vào lớp giá trị phải được định dạng (mà không cần thêm một phương pháp __format__ đến lớp đó)?

Chỉnh sửa: Mục tiêu của tôi là lấy định dạng phụ thuộc vào chuỗi định dạng chứ không phải trên giá trị. Vì vậy, nếu chuỗi định dạng nói "d" hoặc "x", hãy chuyển đổi giá trị thành int và sau đó thành biểu diễn thập phân hoặc thập lục phân. Nếu chuỗi định dạng cho biết "s", hãy chuyển đổi chuỗi thành chuỗi trực tiếp. Như cũ % đã làm.

Thực ra, tôi thậm chí có thể thêm phương thức __format__ vào lớp giá trị. Nhưng làm thế nào để kiểm tra, trong phương pháp đó, nếu đặc tả định dạng đã cho là một đặc tả định dạng số nguyên? Không cần triển khai lại trình phân tích cú pháp đặc tả định dạng của định dạng dựng sẵn.

Chỉnh sửa: Đây là giải pháp với __format__ và ngoại lệ. Bất kỳ ý tưởng tốt hơn?

class MyIntegerTenClass: 
    def __int__(self): 
     return 10 
    def __str__(self): 
     return 'ten' 
    def __format__(self, spec): 
     fmt = '{0:%s}'%spec 
     try: 
      return fmt.format(str(self)) 
     except: 
      return fmt.format(int(self)) 
ten = MyIntegerTenClass() 
print '%d, %02X, %s' % (ten, ten, ten) # ok, prints "10, 0A, ten" 
print '{0:d}, {0:02X}, {0}'.format(ten) # ok, prints "10, 0A, ten" 
+1

Nó nói mười là một chuỗi, bạn đang cố định dạng nó thành một số. –

Trả lời

0

Một cách tiếp cận đầu tiên cho vấn đề này có thể đơn giản chỉ để try nó:

class MyIntegerTenClass: 
    def __int__(self): 
     return 10 
    def __str__(self): 
     return 'ten' 
    def __format__(self, format_spec): 
     try: 
      s = format(str(self), format_spec) 
     except ValueError: 
      s = format(int(self), format_spec) 
     return s 

Nếu MyIntegerTenClassthể được chèn vào chuỗi định dạng như một chuỗi, nó sẽ được. Nếu không, nó sẽ được chuyển đổi thành một int và gửi lại đến format.

>>> print '{0}, {0:s}, {0:d}, {0:02X}, {0:f}'.format(ten) 
ten, ten, 10, 0A, 10.000000 

Nếu bạn muốn các đại diện mặc định là 10 thay vì ten, bạn chỉ cần trao đổi các dòng chuyển đổi:

def __format__(self, format_spec): 
     try: 
      s = format(int(self), format_spec) 
     except ValueError: 
      s = format(str(self), format_spec) 
     return s 

Kiểm tra đầu ra:

>>> print '{0}, {0:s}, {0:d}, {0:02X}, {0:f}'.format(ten) 
10, ten, 10, 0A, 10.000000 

Là một phụ lục, tôi đừng tin rằng bạn sẽ có thể nhận được hành vi mà bạn muốn mà không cần xác định __format__; tuy nhiên, bạn có thể phát triển một cách tiếp cận tinh vi hơn bằng cách sử dụng đối tượng Formatter. Tuy nhiên, tôi nghĩ rằng cách tiếp cận dựa trên ngoại lệ cung cấp cho bạn rất nhiều chức năng tích hợp miễn phí.

+0

Cảm ơn. Dường như chúng tôi có cùng một giải pháp vào khoảng thời gian đó (xem bản chỉnh sửa thứ hai của tôi). Mặc dù giải pháp của bạn có vẻ đẹp hơn một chút vì nó không cần '{0:% s}'% spec. Tôi đã không nhận ra có một chức năng định dạng mà bạn có thể gọi như thế này. – Sebastian

1

chuyển một số nguyên thay vì chuỗi và nó sẽ hoạt động tốt.

>>> print '{0:d}'.format(1) 
1 
>>> print '{0:d}'.format('1') 

Traceback (most recent call last): 
    File "<pyshell#57>", line 1, in <module> 
    print '{0:d}'.format('1') 
ValueError: Unknown format code 'd' for object of type 'str' 
+2

Tôi biết điều đó. Nhưng tôi không muốn vượt qua một số nguyên. Tôi muốn vượt qua một đối tượng của lớp học của tôi mà có thể được chuyển đổi thành một số nguyên. – Sebastian

0

Nó nói mười là một chuỗi, bạn đang cố định dạng nó thành một số.

Hãy thử gói nó trong một dàn diễn viên:

>>> print '{0:d}, {0:02X}'.format(int(ten)) 
10, 0A 
+0

Không hoạt động đối với trường hợp sử dụng của tôi.Tôi không muốn thay đổi giá trị cho định dạng. – Sebastian

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