Pythonで書く場合:
data = {'n': 3, 'k': 3.141594, 'p': {'a': 7, 'b': 8}}
print('{n}, {k:.2f}, {p[a]}, {p[b]}'.format(**data))
del data['k']
data['p']['b'] = None
print('{n}, {k:.2f}, {p[a]}, {p[b]}'.format(**data))
私は得る:
3, 3.14, 7, 8
Traceback (most recent call last):
File "./funky.py", line 186, in <module>
print('{n}, {k:.2f}, {p[a]}, {p[b]}'.format(**data))
KeyError: 'k'
エラーメッセージの代わりに、どのようにしてPython Noneおよび存在しないフィールドをより適切にフォーマットするには?
例を挙げると、出力でもっと見たいものがあります。
3, 3.14, 7, 8
3, ~, 7, ~
理想的には、もちろん、これらの欠損値の代わりに使用される文字列を指定できるようにしたいと思います。
PEP 3101 の推奨事項は、サブクラス Formatter :
import string
class PartialFormatter(string.Formatter):
def __init__(self, missing='~~', bad_fmt='!!'):
self.missing, self.bad_fmt=missing, bad_fmt
def get_field(self, field_name, args, kwargs):
# Handle a key not found
try:
val=super(PartialFormatter, self).get_field(field_name, args, kwargs)
# Python 3, 'super().get_field(field_name, args, kwargs)' works
except (KeyError, AttributeError):
val=None,field_name
return val
def format_field(self, value, spec):
# handle an invalid format
if value==None: return self.missing
try:
return super(PartialFormatter, self).format_field(value, spec)
except ValueError:
if self.bad_fmt is not None: return self.bad_fmt
else: raise
fmt=PartialFormatter()
data = {'n': 3, 'k': 3.141594, 'p': {'a': '7', 'b': 8}}
print(fmt.format('{n}, {k:.2f}, {p[a]}, {p[b]}', **data))
# 3, 3.14, 7, 8
del data['k']
data['p']['b'] = None
print(fmt.format('{n}, {k:.2f}, {p[a]:.2f}, {p[b]}', **data))
# 3, ~~, !!, ~~
設定時に、フィールドまたは属性が見つからない場合は~~
を、フィールド値に無効な形式が使用されている場合は!!
を出力します。 (値エラーのデフォルトを発生させたい場合は、キーワード引数bad_fmt
にNone
を使用するだけです。)
不足しているキーを処理するには、get_field
の両方をサブクラス化して、KeyError
またはAttributeError
とformat_field
をキャッチし、不足しているキーのデフォルト値を返す必要があります。
format_field
エラーをキャッチしているので、スーパークラスからValueError
をキャッチすることで、不正なフォーマットフィールドもキャッチできます。
str.format()
メソッドは、不足しているキーを処理したり値を置き換えたりする直接的な方法を提供しません。
can間接参照のレイヤーを追加します。欠損値とNone
値を処理するマッピングを渡し、その引数のみを使用するようにフォーマットを変更します。
_class PlaceholderFormatValue():
def __format__(self, spec):
return '~'
def __getitem__(self, name):
# handle further nested item access
return self
class formatting_dict(dict):
def __getitem__(self, name):
value = self.get(name)
if isinstance(value, dict):
# rewrap nested dictionaries to handle missing nested keys
value = type(self)(value)
return value if value is not None else PlaceholderFormatValue()
print('{0[n]}, {0[k]:.2f}, {0[p][a]}, {0[p][b]}'.format(formatting_dict(data)))
_
現在、すべてのスロットは位置引数_0
_を参照しますが、これは辞書のように扱われますが、キー検索は常に成功し、欠損値とNone
の両方がプレースホルダー値に置き換えられます。
ここで、PlaceholderFormatValue()
は、フォーマット仕様が与えるものに関係なく、値をフォーマットに補間できることを保証します。これにより、たとえば_{0[k]:.2f}
_が機能します。
dict
値をラップし、PlaceholderFormatValue
がアイテムアクセスを処理することにより、上記はネストされたキーまたはディクショナリ全体の提供の失敗も処理できます。
_>>> data = {'n': 3, 'k': 3.141594, 'p': {'a': 7, 'b': 8}}
>>> del data['k']
>>> data['p']['b'] = None
>>> print('{0[n]}, {0[k]:.2f}, {0[p][a]}, {0[p][b]}'.format(formatting_dict(data)))
3, ~, 7, ~
>>> del data['p']['a']
>>> print('{0[n]}, {0[k]:.2f}, {0[p][a]}, {0[p][b]}'.format(formatting_dict(data)))
3, ~, ~, ~
>>> del data['p']
>>> print('{0[n]}, {0[k]:.2f}, {0[p][a]}, {0[p][b]}'.format(formatting_dict(data)))
3, ~, ~, ~
_
書式設定を個別に行うことができる場合は、Template.safe_substitute
欠損値を適切に処理します:
>>> from string import Template
>>> t = Template("$a $b $c")
>>> t.safe_substitute(a=3)
'3 $b $c'