私はいくつかの衝突検出を行っていますが、2つの異なるコンテキストで同じ関数を使用したいと思います。ある文脈では、私はそれが次のようなものになりたいです
def detect_collisions(item, others):
return any(collides(item, other) for other in others)
そして別の中で、私はそれがなりたいです
def get_collisions(item, others):
return [other for other in others if collides(item, other)]
ここに2つの関数を書くというアイデアは本当に嫌いです。名前をまっすぐに保つことは1つのターンオフであり、衝突検出へのインターフェースを複雑にすることは別のことです。だから私は考えていました:
def peek(gen):
try:
first = next(gen)
except StopIteration:
return False
else:
return it.chain((first,), gen)
def get_collisions(item, others):
get_collisions.all = peek(other for other in others if collides(item, other))
return get_collisions.all
今、私がチェックをしたいとき、私は言うことができます:
if get_collisions(item, others):
# aw snap
また
if not get_collisions(item, others):
# w00t
そして、私が実際にそれらを調べたい他の文脈では、私は次のことができます:
if get_collisions(item, others):
for collision in get_collisions.all:
# fix it
どちらの場合も、必要以上の処理は行いません。
これは最初の2つの関数よりも多くのコードであると認識していますが、次の利点もあります。
衝突検出へのインターフェイスを、ノードが中間レベルではなく最上位レベルにあるツリーとして保持します。これはもっと簡単なようです。
便利なピーク機能で自分自身をフックアップします。もう一度使用すると、実際に記述しているコードは少なくなります。(YAGNIに応えて、持っていればそうします)
それで。あなたが私がどこに住んでいるかを知っていることわざの殺人マニアであるならば、私が上記のコードを書いたならば、私はあなたからの訪問を期待しますか?もしそうなら、あなたはこの状況にどのようにアプローチしますか?