短いが完全な要約
関数 (クラス ファクトリ) のユーザーが、関数を使用するときにグローバル インポートを挿入/上書きできるようにしたい (以下の理論的根拠のより長い説明)。しかし、渡すことができる約 10 の異なる変数があり、コードに多数の非常に反復的な行が追加されます。(確かに、呼び出しも複雑になります:P) 現在、私は次のようなことを行っています (これらすべてを単純化しただけです)。実行可能にするために、ダミー クラスを使用していますが、実際のスクリプトでは などを使用しますimport pkg1
。これは、クラス ファクトリなどよりも明確で短いと考えました。
class Dummy(object): pass
pkg1, pkg2 = Dummy(), Dummy()
pkg1.average = lambda *args : sum(args) / len(args)
pkg2.get_lengths = lambda *args : map(len, args)
def get_average(*args, **kwargs):
average = kwargs.get("average") or pkg1.average
get_lengths = kwargs.get("get_lengths") or pkg2.get_lengths
return average(*get_lengths(*args))
adjusted_length = lambda *args: map(len, args) + [15]
print get_average([1,2], [10, 4, 5, 6]) == 3 # True
print get_average([1,2], [10, 4, 5, 6], get_lengths=adjusted_length) == 7 # True
関連する SO の質問
このスタック オーバーフローの投稿: Modifying locals in Pythonは特に関連性があるようで、当初はローカル ディクショナリに保存してローカルを上書きしたかったのですが、(1) うまくいかなかったようで、(2) うまくいかなかったようです。考え。ということで、何か他に方法がないか検討中です。
これは有望に見えました ( Python で別のモジュールのグローバルにオブジェクトを追加する) が、モジュールと同じ方法で現在のファイルのグローバルにアクセスする方法がよくわかりません。(そして、この質問 - python: mutating `globals` to dynamic put things in scope - は、(最終的に)これを使用してクラスを定義しているため、実際には適用されません)。
すべてを exec ステートメントでラップできると思います (この投稿のように - python exec()のグローバルとローカル) が、それは面倒であり、エラー チェック/リンティングなどを行うのがはるかに難しいことを意味します。
だからここに私がしたいことがあります。(注: from pkg1 import average
ANDを使用from pkg2 import get_lengths
していましたが、例をより明確にしたかった (これを実行するには、上記の pkg1 と pkg2 をコピーする必要があります))
average = pkg1.average
get_lengths = pkg2.get_lengths
def get_average(*args, **kwargs):
localvars = locals()
for k in ("get_lengths", "average"):
if kwargs.get(k, None) and kwargs[k] is not None:
localvars[k] = kwargs[k]
return average(*get_lengths(*args))
print get_average([1,2], [10, 4, 5, 6]) == 3 #True
print get_average([1,2], [10, 4, 5, 6], get_lengths=adjusted_length) == 7 # False, is 3
私の特定のユースケースの根拠
現在、動的に生成されたクラス ファクトリ (SQLAlchemy mixin として使用) を作成しようとしていますが、クラスのユーザーが代替コンストラクターを渡せるようにして、SQLAlchemy アダプターなどを使用できるようにしたいと考えています。
たとえば、Flask-SQLAlchemy は SQLAlchemy と同じインターフェイスを提供しますが、より多くの機能を提供するためにすべての SQLAlchemy オブジェクトをラップするカスタム オブジェクト/クラス ( db
) を提供します。