これについて考えると、可変引数展開が一度にすべて展開されるという事実の他に、'{2} {1} {0}'
のように、format
が必ずしも引数を順番に取るわけではないという事実もあります。
format
が、別々の引数を必要とするのではなく、正しいことをするシーケンスを構築するだけで、これを回避することができます。ここでは簡単な例です:もちろん
class DefaultList(list):
def __getitem__(self, idx):
try:
return super(DefaultList, self).__getitem__(idx)
except IndexError:
return '-'
あなたの現実のバージョンは、任意のiterableをラップlist
をサブクラス化していない、そしておそらく、tee
または内部キャッシュを使用して、要求に応じて新しい値を引き出すために持っている唯一の不履行なりますあなたが終わりを過ぎたとき。(ActiveStateで「レイジーリスト」や「レイジーシーケンス」のレシピを検索したい場合がありますが、これにはいくつかのレシピがあります)。
これはどうやって私たちを助けますか?それはしません。 のDefaultList
は、タプルを作成しようとするだけで、私たちがすでに持っているのと同じ数の引数を与えることができます。しかし、代わりにargsのシーケンスを取ることができるformat
のバージョンをお持ちでしたらどうでしょうか?その後、あなたはDefaultList
を渡すことができ、それはうまくいくでしょう。
あなたはそれを持っています:Formatter.vformat
。
>>> string.Formatter().vformat('{0} {1} {2}', DefaultList([0, 1]), {})
'0 1 -'
あなたはstr
メソッドを介して明示的に代わりの暗黙的Formatter
を使用しているいったんしかし、さらに簡単な方法は、あります。もちろん
class DefaultFormatter(string.Formatter):
def __init__(self, default):
self.default = default
# Allow excess arguments
def check_unused_args(self, used_args, args, kwargs):
pass
# Fill in missing arguments
def get_value(self, key, args, kwargs):
try:
return super(DefaultFormatter, self).get_value(key, args, kwargs)
except IndexError:
return '-'
f = DefaultFormatter('-')
print(f.vformat('{0} {2}', [0], {}))
print(f.vformat('{0} {2}', [0, 1, 2, 3], {}))
それでもシーケンスプロトコルを提供し、何かにあなたのイテレータをラップする必要があるとしている:あなたは、ちょうどそのget_value
方法および/またはそのcheck_unused_args
を上書きすることができます。
言語が「iterable unpacking」プロトコルを使用している場合は、問題はより解決します。そのようなことを提案するpython-ideasスレッド、およびそのアイデアが持つすべての問題については、hereを参照してください。 (format
関数は、これを難解にしてしまうことに注意してください。なぜなら、インタプリタを魔法に使うのではなく、アンパックプロトコルを直接使用しなければならないからです。しかし、それを仮定すると、単純な汎用ラッパーで、そのためには__unpack__
を処理します。)
これがありました。より良いアプローチを提案できますか?私は、無駄な(発電機を使用する目的を破って、リストがする)最大の長さの発電機をつくることに満足しておらず、いつも働くことが保証されません。 – user443854
@ user443854: 'itertools.islice()'を使ってジェネレータを制限することができます。 –
私は 'itertools.islice()'について認識していますが、ここでどのように適用されるかわかりません。私はそれを使う前に必要な要素の数を知る必要があります。私は何か違うものを達成したいと思っていました。普通の英語で、私は通訳者に伝えたい:ここにはジェネレータがあり、それは必要な回数だけ繰り返すが、それ以上は繰り返さない。 – user443854