ある時点で、多くの引数を持つ関数を見つけるかもしれません。いくつかの引数を組み合わせてスーパー引数にすることが理にかなっている場合があります。私はこれを口述筆記で頻繁に行ってきましたが、今はより良い方法を検討しています。
回したい...
def do_something(ax, ay, az, bu, bv, c):
# Do something
...に...
def do_something(a, b, c):
# Do something
... a
およびb
には、それらのサブバリエーションが含まれます。
これを行う1つの方法は、次のことです。
A = namedtuple('A', 'x, y, z')
a = A(ax, ay, az)
B = namedtuple('B', 'u, v')
b = B(bu, bv)
ただし、これはより簡単に見えます。
a = SimpleNamespace(x=ax, y=ay, z=az)
b = SimpleNamespace(u=bu, v=bv)
欠点は何ですか? a
とb
が適切に入力されていないという事実は?それらはAおよびBオブジェクトではありませんか?
(ところで、変数名については心配しないでください。通常、短い変数名としては使用しません。)
SimpleNamespace
は基本的に、辞書の上にある素敵な外観です。インデックスキーの代わりにプロパティを使用できます。非常に柔軟で操作が簡単なので、これは素晴らしいことです。
その柔軟性の欠点は、構造が提供されないことです。誰かがSimpleNamespace(x=ax, y=ay)
(およびdel a.z
を後で呼び出すこと)を妨げるものは何もありません。このインスタンスが関数に渡されると、フィールドにアクセスしようとしたときに例外が発生します。
対照的に、namedtuple
を使用すると、構造化タイプを作成できます。型には名前が付けられ、その型が持っているはずのフィールドが認識されます。これらの各フィールドがないとインスタンスを作成できず、後で削除することもできません。さらに、インスタンスは不変なので、a.x
の値は常に同じであることがわかります。
SimpleNamespace
が提供する柔軟性が必要かどうか、またはnamedtuple
によって提供される構造と保証を希望するかどうかは、あなた次第です。
私は構造化されたものとそうでないものの答えが本当に好きなので、以下に具体的な例を示します。
SimpleNamespace
は、_
で始まるキーを受け入れます。たとえば、JSONを制御せずにフィールド名を持つオブジェクトに変換する迅速で簡単な方法を探している場合、これは非常に便利です。
d = {"_id": 2342122, "text": "hi there!"} # Elasticsearch gives this id!
e = SimpleNamespace(**d) # works
Name = namedtuple("Name", sorted(d)) # ValueError so we can't do Name(**d)
上記のように、namedtuple
はSimpleNamespace
が絶対に提供しない追加のオブジェクトを提供することがわかります。各SimpleNamespace
は実際には「ユニークなスノーフレーク」ですが、namedtuple
は具体的な値でインスタンス化されることなく存在します。具体的な値を一般化する抽象化が必要な場合は、おそらくそれを優先する必要があります。
SimpleNamespace
の概要
オブジェクトの構築中に属性を初期化できます。
_sn = SimpleNamespace(a=1, b=2)
_
読みやすい
_repr(): eval(repr(sn)) == sn
_
デフォルトの比較を上書きします。 id()
で比較する代わりに、属性値を比較します。