週末副業記

土日は副業エンジニアのブログです。副業に関することを投稿します。

関数の定義の仕方とset()について[Python3.0]


 

f:id:aisakakun:20160302010225p:plain

ようやく、checkIOの「Elementary」が終わりました。 

最後、手間取って中々終わりませんでしたが、、

 

最後のお題は、「データ構造の体得」

 

いつもお世話になっているモジュールを、自分で作ってみる。

といったイメージです。

 

クラスにおける、関数「add」「remove」「name」「connected」というそれぞれ役割をもったものを作るのですが、

ここでいうそれぞれの役割は

「add(connection)」: "connection"が新しかったら"True"を返し、すでに存在していたら"False"を返す

「remove(connection)」:"connection"が存在していたら"True"、"False"はその逆。

 

「names()」:誰かと関係のある名前だけを集合として返す。

 

「connected(name)」:"name"に関する名前を返す。なかったら空の集合を返す。

 といった感じです。 よくわからなければ、実際にcheckIOの問題をご覧ください...

 

そしてこの問題を解決すべく、私が作成したものがこれです。

 

 

この中で、最も苦労したのは、names( ) のところです。

set( ).union( )とか知らない...

 

なので、union( )について解説します。

ここにもありますが、

8.7. sets — ユニークな要素の順序なしコレクション — Python 2.7.x ドキュメント

 

set( ) . union( t ) : set ( ) と t の両方の要素からなる新しい集合

 

となります。

はじめの__init__の段階で、self.xx = list ( xx )

リストにしているので、リストを分解して変数を渡すことができる

"*(アスタリスク)"を用いて、

return set().union(*self.connections)

という風に記述します。詳しくはこのサイトがよいです。

*args **kwargsの意味

 

頭にset( ) をつけているのは、tが空っぽのときに空の集合を返すためです。

また、.union( ) はset型のオペレータなので、

set( ) 型のものがないと使えません。

そして、元のself.connectionsというリストは、単純なリストではなく、

辞書が内包されている特殊なリストなので、そのままset(self.connections)を適用することはできません。

ちなみに、試してみると

In [26]: s

Out[26]: [{'1', '2'}, {'1', '3'}]

 

In [27]: b = [{}]

 

In [28]: set().union(*b)

Out[28]: set()

 

In [29]: set(s)

Traceback (most recent call last):

 

File "<ipython-input-29-d35473c9f65c>", line 1, in <module>

set(s)

 

TypeError: unhashable type: 'set'

 

 となり、エラーになります。

なので、リストの要素を一つずつset( )に適用していくことによって、

結果的に

In [33]: set().union(*s)

Out[33]: {'1', '2', '3'}

となります。

 

関数の定義の仕方。というテーマなのに、set ( ) に関することを中心に述べてしまいましたが、関数とそのオペレータとの関係については

ソースコードを見ていただければわかるとおもいます。

 

self. と使うのは、はじめに引数として用いたものを記憶し、

それを様々なことに生かすことができるためです。

この例を用いますと、

 

In [5]: f = Friends([{"1", "2"}, {"3", "1"}])

 

In [6]: f.names()

Out[6]: {'1', '2', '3'}

 

In [7]: f = Friends*1

 

In [8]: f.names()

Out[8]: {'a', 'b', 'c', 'd'}

 

In [9]: f.remove({"d", "c"})

Out[9]: True

 

In [10]: f.names()

Out[10]: {'a', 'b', 'c'}

 

このように、はじめに「f」に代入したものを基準として

.names( ) のようにオペレータを適用することが、今までのプログラミングでもあったと思うのですが、その裏側はselfを使用することによって実現されていた、ということになるんですね。

 

 

次回のcheckIO編は、なぜか飛ばしていた、「HOME」をやっていこうと思います。

 

----------------------------------------------------------------------------------------------------

そういえば、この間この本を読み終えたのでまた感想書いていきます。

 

これからの「正義」の話をしよう (ハヤカワ・ノンフィクション文庫)

これからの「正義」の話をしよう (ハヤカワ・ノンフィクション文庫)

 

 それでは。

*1:{"a", "b"}, {"b", "c"}, {"c", "d"}