2012-07-12 8 views
6

これはthis question about floatsとほぼ同じ問題です。「{0:d}」の文字列の書式設定が整数に変換されません

数値が整数に変換されると、古い%dが変換されますが、フォーマットは変換されません。

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' 

(そのクラスに__format__メソッドを追加せずに)フォーマットされる値のクラスを触れることなく、フォーマットの動作を変更する方法はありますか?

編集:私の目標は、フォーマット文字列に依存してフォーマットを取得することですが、値には依存しません。 フォーマット文字列に "d"または "x"と書かれている場合は、値をintに変換してから10進数または16進数に変換します。 フォーマット文字列が "s"と書かれている場合は、文字列に直接変換してください。古いように%しました。

実際には、値のクラスに__format__メソッドを追加することもできます。しかし、その方法で、指定された書式指定が整数書式指定であるかどうかを調べるにはどうすればよいですか?組み込み形式の形式仕様パーサーを再実装することなく

編集:ここには__format__の例外と例外があります。どんな良いアイデアですか?

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

10は文字列で、数値として書式を設定しようとしています。 –

答えて

0

この問題への最初のアプローチは、単にtryそれにあるかもしれない:としてフォーマット文字列に挿入することができMyIntegerTenClass場合

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 

文字列、それはなります。そうでない場合、それはintに変換され、formatに再送信されます。

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

デフォルトの表現は10の代わりtenになりたい場合は、あなただけの変換線入れ替える必要があります。

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

テスト出力:補遺として

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

を、私はあなたが定義することなくあなたが望む振る舞いを得ることができると信じていない__format__;ただし、Formatterオブジェクトを使用すると、より洗練されたアプローチを開発できます。それでも、例外ベースのアプローチでは、多くの組み込み機能が無料で提供されていると思います。

+0

ありがとうございます。私たちはほぼ同じ時に同じ解決策を得ているようです(2回目の編集を見てください)。 '{0:%s}'%スペックは必要ないので、あなたのソリューションは少し良く見えますが。私はあなたがこれを呼び出すことができるフォーマット機能があることに気付かなかった。 – Sebastian

1

文字列の代わりに整数を渡すと正常に動作します。

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

私はそれを知っていました。しかし、私は整数を渡したくありません。整数に変換できるクラスのオブジェクトを渡したいと思います。 – Sebastian

0

10は文字列で、数値として書式を設定しようとしています。

はキャストでそれをラップしてみてください。

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

私の使用例では機能しません。私はformatに与えられた値を変更したくありません。 – Sebastian

関連する問題