Python 3.4以降では、dictを使用しないときにSimpleNamespaceでnamedtupleを使用する必要があるのはなぜですか?


11

ある時点で、多くの引数を持つ関数を見つけるかもしれません。いくつかの引数を組み合わせてスーパー引数にすることが理にかなっている場合があります。私はこれを口述筆記で頻繁に行ってきましたが、今はよりよい方法を検討しています。

回したい...

def do_something(ax, ay, az, bu, bv, c):
    # Do something

...に...

def do_something(a, b, c):
    # Do something

...場所abそのサブバリエーションを含みます。

これを行う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)

欠点は何ですか?事実abうまく型付けされていませんか?それらはAおよびBオブジェクトではありませんか?

(ところで、変数名については心配しないでください。通常、短い変数名としては使用しません。)


1
それ自体に欠点はありません。それらは単なる異なるものです。まず、名前空間は変更可能ですが、名前付きタプルは不変です。可変性は不変性よりも良いですか、悪いですか?それはあなたが何を必要としているか、何を望んでいるかに依存し、多くの場合それは問題ではありません。関数はおそらく必要な属性を持つ任意のオブジェクトで機能します。それを構築する方法は呼び出し元次第です。
モニカへの危害を停止する

@五葉ありがとうございます。「欠点」は、不器用な言い方でした。一方が他方よりも本質的に優れているという意味ではありませんでした。ただ長所と短所が欲しかった。再度、感謝します。
アンドレ・クリストファー・アンダーセン

1
4行目は "b = B(bu、bv)"のように見えませんか?
Alen Siljak

@AlenSiljakはい、そうするべきです。直します。
アンドレ・クリストファー・アンダーセン

回答:


21

SimpleNamespace基本的には辞書の上にある素晴らしいファサードです。インデックスキーの代わりにプロパティを使用できます。これは非常に柔軟で操作が簡単なので便利です。

その柔軟性の欠点は、構造が提供されないことです。誰かが電話をかけるのを止めることは何もありませんSimpleNamespace(x=ax, y=ay)(そしてdel a.zある時点で)このインスタンスが関数に渡されると、フィールドにアクセスしようとしたときに例外が発生します。

対照的に、namedtuple構造化タイプを作成できます。型には名前が付けられ、その型が持っているはずのフィールドがわかります。これらの各フィールドがないとインスタンスを作成できず、後で削除することもできません。さらに、インスタンスは不変であるため、の値a.xは常に同じであることがわかります。

SimpleNamespace提供する柔軟性が必要かどうか、またはによって提供される構造と保証を希望するかどうかは、あなた次第ですnamedtuple


2

私は構造化されたものとそうでないものの答えが本当に好きなので、以下に具体的な例を示します。

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具体的な値でインスタンス化されることなく存在します。具体的な値を一般化する抽象化が必要な場合は、おそらくそれを優先する必要があります。


1

のまとめ SimpleNamespace

オブジェクトの構築中に属性を初期化できます。

sn = SimpleNamespace(a=1, b=2)

読みやすい

repr(): eval(repr(sn)) == sn

デフォルトの比較を上書きします。で比較する代わりに、id()属性値を比較します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.