2009-04-15 5 views
3

私がしようとした場合:メソッド呼び出しを 'set()'ビルトインにチェーンすることができますか? (そしてなぜない?)

mi_list = ['three', 'small', 'words'] 
mi_set = set(mi_list) 
mi_set.remove('small') 
print mi_set 

私が手:

私が期待するものである
set(['three', 'words']) 

。私がしようとするのに対し:

mi_list = ['three', 'small', 'words'] 
mi_set = set(mi_list).remove('small') 
print mi_set 

私が取得:

None 

なぜ?

私は存在しない要素削除しようという点で、手がかりがあります疑いがある - 例えば「ビッグ」 - エラーが報告されます:

KeyError: 'big' 

答えて

20

set.removeは何も返しません(なし)。

あなたのコードでは、戻り値set.removeが変数mi_setに割り当てられます。したがって、mi_setはNoneです。

+0

+1これは私が以前に実行した微妙なものです(別の方法ではありますが)。 –

+0

+1。それは流暢なインターフェイスではありません。 – vartec

+0

+1それはlist.sortメソッドに似ていますが、オブジェクトを変更しますが、返りません。 – kurosch

0

はあなたにremove関数が返すことを確認していますが値?

+0

値を返しますが、それはまれにNoneになります。 –

+0

よくTorsten :-) –

+0

私はSocraticメソッドに対して何も持っていませんが、私はこれが質問に答えるのを助けるとは思わないと思います。 – allyourcode

1

移動するための方法、あなたのケースでは、違いメンバーを使用することです:

>>> a = set(["a", "b", "c"]) 
>>> a = a.difference(["a"]) 
>>> print a 
set(['c', 'b']) 

違いはが現在のセットに行為(変更のpythonライブラリオブジェクトのメンバ関数を削除することですインスタンスは通常Noneを返します)、の差異が新しいセットを作成して返します。

1

なぜNoneが返されますか? .remove、.addなどはNoneを返します:)それだけです。彼らは連鎖をサポートしていません。

setは、その場所を変更する方法を使用しています。あなたは、連鎖使用するセットの独自のバージョンを作成することができ、それはいくつかの問題を引き起こす可能性があります:

class chain_set(set): 
    def chain_add(self, x): 
     newself = self.copy() 
     newself.add(x) 
     return newself 

cs = chain_set([1,2,3,4]) 
cs.chain_add(5) 
# chain_set([1, 2, 3, 4, 5]) 
cs.chain_add(7) 
# chain_set([1, 2, 3, 4, 7]) 
cs.chain_add(7).chain_add(8) 
# chain_set([1, 2, 3, 4, 7, 8]) 

問題がある - あなたはcs自体が変化することを期待しますか?

オリジナルのセット(バグを見つけにくい場合があります)を変更するか、毎回セットをコピーしたいですか(大きなセットでは遅くなるかもしれません)。あなたが必要とする行動が分かっていて、それについて覚えているならば、あなた自身のセット実装を進めてください。

8

side-effects返すなしの原因となるメソッドは、一般的な慣習があります。たとえば、list.sort、list.append、set.add、set.remove、dict.updateなどがあります。

これは基本的にバグを回避するのに役立ちます。 mi_setというセットがあったとします。あなたが書くことができる場合:

mi_set2 = mi_set.remove('small') 

は、読者は考えるかもしれない:「mi_set2mi_set異なっています」。しかし、これは当てはまりません!そして混乱は、間違ってデータ構造を共有することによって引き起こされる微妙なバグにつながるかもしれません。だからNoneを返すことで、上記のようなメソッドが新しいものを作成するのではなく、オブジェクトを修正することを覚えておく必要があります。

また、長い議論hereも参照してください。このスレッドより、sorted()reversed()のようなメソッドが追加されていますが、

[list.popは、歴史的な理由から、このルールの例外です。これは、スタックのようなリストを使用できるようにします。それでも、リストではなくオブジェクトを返します。]

+0

+1私はこれが好きです....非常にうまく説明しました –

+0

Nice answer。ソートされ、元のコンテナを変更することはないので、ここで与えられた根拠は変更されません。 – babbageclunk

+0

はい、私はsorted()とreversed()が私の投稿の意味を変えないことを知っています。人々がそのスレッドで提起したいくつかの問題に対する解決策であるため、私はそれらについて言及しました。 –

0

removeは、何も返さずに元のセットを変更します(むしろNoneを返します)。この例では、あなたがそれを削除呼び出したときに、元のオブジェクトに何が起こるかを示しています。あなたの質問の他の部分に答えるために

Python 3.0.1 (r301:69561, Feb 13 2009, 20:04:18) [MSC v.1500 32 bit (Intel)] on win32 
Type "help", "copyright", "credits" or "license" for more information. 
>>> lst = [1,2,3] 
>>> s1 = set(lst) 
>>> s1 
{1, 2, 3} 
>>> s2 = s1.remove(2) # instead of reassigning s1, I save the result of remove to s2 
>>> s1 
{1, 3} # *** 2 is not an element in the original set *** 
>>> s2 # s2 is not a set at all! 
>>> 

、例外は、removeがセットから引数を削除しようとしたことを示しているが、言えませんでした引数がセットにないためです。逆に、removeは成功を示すためにNoneを返します。

関連する問題