7

これは、 floats に関するこの質問と同じ問題です。

整数に変換できる値を取得した場合、古い%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"
4

3 に答える 3

1

この問題への最初のアプローチは、単純に次のようにするtryことです。

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 できる場合は、挿入されます。そうでない場合は、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オブジェクトを使用してより洗練されたアプローチを開発できます。それでも、例外ベースのアプローチにより、多くの組み込み機能が無料で提供されると思います。

于 2012-07-12T19:25:00.767 に答える
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'
于 2012-07-12T18:40:21.560 に答える
0

10 は文字列であると表示されていますが、数値としてフォーマットしようとしています。

キャストでラップしてみてください:

>>> print  '{0:d}, {0:02X}'.format(int(ten))
10, 0A
于 2012-07-12T18:43:35.217 に答える