dict.setdefault
の小さな悩みは、最初の引数が既に辞書のキーであっても、常に2番目の引数(もちろん与えられたとき)を評価するということです。例えばlazy setdefaultを実装する方法は?
:これは、以下のようなouptut生成
import random
def noisy_default():
ret = random.randint(0, 10000000)
print 'noisy_default: returning %d' % ret
return ret
d = dict()
print d.setdefault(1, noisy_default())
print d.setdefault(1, noisy_default())
:最後の行が確認よう
noisy_default: returning 4063267
4063267
noisy_default: returning 628989
4063267
をキー1
である。この点によってので、noisy_default
の第二の実行は、不要ですd
(値4063267
)に既に存在します。
setdefault
メソッドが第2引数を遅延評価するdict
のサブクラスを実装することは可能ですか?
EDIT:
以下がBrenBarnさんのコメントとパベルAnossovの答えに触発実装です。その間、基本的なアイデアは本質的に同じなので、私は先に進み、怠惰なバージョンを実装しました。上記d.setdefault
への第2引数は今呼び出し可能ではなく、関数呼び出しであることを
noisy_default: returning 5025427
5025427
5025427
は予告:
class LazyDict(dict):
def get(self, key, thunk=None):
return (self[key] if key in self else
thunk() if callable(thunk) else
thunk)
def setdefault(self, key, thunk=None):
return (self[key] if key in self else
dict.setdefault(self, key,
thunk() if callable(thunk) else
thunk))
は今、スニペット
d = LazyDict()
print d.setdefault(1, noisy_default)
print d.setdefault(1, noisy_default)
は、このような出力を生成します。
LazyDict.get
またはLazyDict.setdefault
の第2引数が呼び出し可能でない場合、それらは対応するdict
メソッドと同じように動作します。 1はデフォルト値そのものとして呼び出し可能に合格したい場合
(すなわち、はないと呼ばれることを意図し)、またはと呼ばれることが呼び出し可能な場合には、引数を必要とし、先頭に追加適切な引数にlambda:
。例:
d1.setdefault('div', lambda: div_callback)
d2.setdefault('foo', lambda: bar('frobozz'))
など、get
とsetdefault
をオーバーライドするというアイデアが好きで、および/または要求可能のためにテストする結果必要ない人は、代わりにこのバージョンを使用することができます。
class LazyButHonestDict(dict):
def lazyget(self, key, thunk=lambda: None):
return self[key] if key in self else thunk()
def lazysetdefault(self, key, thunk=lambda: None):
return (self[key] if key in self else
self.setdefault(key, thunk()))
第2引数を評価しないようにすることはできません。あなたがしなければならないことは、その引数を関数(例えば、 'lambda ')で囲み、必要に応じて' setdefault'関数を呼び出すことだけです。 – BrenBarn
'lazyget'、' lazysetdefault'の署名と 'thunk()'の呼び出しに '* args、** kwargs'を追加することを提案できますか?これはあなたの怠惰なものがパラメータを取ることができます。例えば'ldap.lazysetdefault( 'total'、sum、[1,2,3,4]、start = 2)' – Hounshell