2012-07-12 26 views
6

tam sayıya dönüştürülmez. Bu, this question about floats ile aynı sorunla ilgilidir.“{0: d}” ile dize biçimlendirmesi,

Bir tam sayıya dönüştürülebilen bir değere sahip olduğunuzda, eski %d bunu dönüştürür, ancak biçimlendirmez.

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' 

(bu sınıfa bir __format__ yöntem eklemeden) biçimlendirilmesini değer sınıfı dokunmadan, format davranışını değiştirmek için bir yol var mı?

Düzenleme: Amacım, biçimlendirmeyi biçim dizesine bağlı olarak değil, değerde elde etmektir. Biçim dizgisi "d" veya "x" yazıyorsa, değeri int'ye ve ardından ondalık veya onaltılık gösterime dönüştürün. Biçim dizgisi "s" yazıyorsa, onu doğrudan dizeye dönüştürün. Eski % gibi.

Aslında, değerin sınıfına bir __format__ yöntemi ekleyebilirim. Ancak, belirtilen biçim belirtimi bir tamsayı biçim belirtimiyse, bu yöntemde nasıl denetlerim? Yerleşik formatın biçim belirtimi ayrıştırıcısını yeniden oluşturmadan.

Düzenleme: İşte, __format__ ile bir çözüm ve istisnalar. Daha iyi bir fikir var mı?

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

On bir dizedir, bir sayı olarak biçimlendirmeye çalışıyor. –

cevap

0

bu sorunun birinci yaklaşım sadece try nedeniyle olabilir o:

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 

MyIntegerTenClass biçim dizgesi olarak eklenebilir Eğer bir dize olacak. Değilse, bir int olarak dönüştürülecek ve format'a yeniden gönderilecektir.

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

Testi çıkışı: zeyilname olarak

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

, ben

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

Eğer sadece ihtiyaç dönüşüm hatları takas, varsayılan gösterimi yerine ten ait 10 olmasını istiyorsanız __format__ tanımlamaksızın istediğiniz davranışı alabileceğinizi düşünmeyin; ancak, Formatter nesnesini kullanarak daha karmaşık bir yaklaşım geliştirebilirsiniz. Yine de, istisna temelli yaklaşımın size birçok ücretsiz yerleşik işlevsellik kazandırdığını düşünüyorum.

+0

Teşekkürler. Aynı çözümü aynı anda aldığımız anlaşılıyor (ikinci düzenlememe bakın). Çözümünüz biraz daha hoş görünse de, '{0:% s}'% spec. Bunun gibi arayabileceğiniz bir format fonksiyonu olduğunu fark etmedim. – Sebastian

1

Bir dize yerine bir tam sayı geçirir ve iyi çalışır.

>>> 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

Bunu biliyordum. Ama ben bir tamsayı geçmek istemiyorum. Sınıfımın bir tamsayıya dönüştürülebilen bir nesnesini geçmek istiyorum. – Sebastian

0

On bir dizedir, bir sayı olarak biçimlendirmeye çalışıyor demektir.

alçıda sararak deneyin:

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

Kullanım durumum için çalışmıyor.Biçime verilen değeri değiştirmek istemiyorum. – Sebastian