[Python3 入門 7日目] 3章 Pyの具：リスト、タプル、辞書、集合（3.3〜3.8）

#3.3 タプル
タプルはリストと異なり、イミュータブルである。
そのためタプルを定義した後での要素の追加、削除、変更は不可である。

##3.3.1 ()を使ったタプルの作成
タプルを定義するのは値をくぎるカンマ。()を使ってもエラーにならないので、値全体を()で囲むことが慣習となっている。


```py
#タプルを使えば一度に複数の変数を代入できる。
>>> marx_tuple = ("Groucho","Choico","Harpo")
>>> marx_tuple
('Groucho', 'Choico', 'Harpo')
>>> a,b,c=marx_tuple
>>> a
'Groucho'
>>> b
'Choico'
>>> c
'Harpo'

>>> password = "aaaa"
>>> icecream = "bbbb"
>>> password,icecream =icecream,password
>>> password
'bbbb'
>>> icecream
'aaaa'

#変数関数のtuple()を使うと他のものからタプルを作成できる。
>>> marx_list=["Groucho","Choico", 'Haapo']
>>> tuple(marx_list)
('Groucho', 'Choico', 'Haapo')
```

##3.3.2 タプルとリストの比較

タプルの特徴
- タプルは消費スペースが少ない
- タプルは辞書のキーとして使える
- タプルの要素は誤って書き換える危険がない
- 名前付きタプルはオブジェクトの単純な代用品として使える
- 関数の引数はタプルとして渡される。

#3.4 辞書
辞書はリストに似ているが要素の順序が管理されていないので要素を選択する時に0や1などのオフセットを使用しない。その代わりに個々の値に**一意なキー**を与える。キーはイミュータブル型ならなんでも良い。

##3.4.1 {}による作成
辞書を作るにはkey:valueのペアをカンマで区切って、{}で囲む。

```py

>>> empty_dict ={}
>>> empty_dict
{}
>>> bierce ={
... "day":"A period of twenty-four hours,mostly misspent",
... "positive":"Mistaken at the top of one's voice",
... "misfortune":"The kind of fortune tha never misses",
... }
>>> bierce
{'day': 'A period of twenty-four hours,mostly misspent', 'positive': "Mistaken at the top of one's voice", 'misfortune': 'The kind of fortune tha never misses'}

```

##3.4.2 dict()を使った変換
dict()関数を使えば二つの値のシーケンスを辞書に変換できる。
シーケンスの先頭要素がキー、第二要素が値になる。

```py
#二要素のタプルのリスト
>>> lol = [["a","b"],["c","d"],["e","f"]]
>>> dict(lol)
{'a': 'b', 'c': 'd', 'e': 'f'}
>>> lol = [("a","b"),("c","d"),("e","f")]

#二要素のリストのタプル
>>> dict(lol)
{'a': 'b', 'c': 'd', 'e': 'f'}
>>> lol = (["a","b"],["c","d"],["e","f"])
>>> dict(lol)
{'a': 'b', 'c': 'd', 'e': 'f'}

#二字の文字列のリスト
>>> los = ["ab","cd","ef"]
>>> dict(los)
{'a': 'b', 'c': 'd', 'e': 'f'}

#二文字の文字列のタプル
>>> los = ("ab","cd","ef")
>>> dict(los)
{'a': 'b', 'c': 'd', 'e': 'f'}


```


##3.4.3 [key]による要素の追加、変更
キーを使って要素を参照し、値を代入する。辞書にそのキーが既にある場合は既存の値が新しい値に置き換えられる。
**キーがまだない場合は値と共に辞書に追加される。**

```py

#キーが存在していないためキーと値のセットで辞書に追加される
#キーが既に存在しているため値の置き換えを行う
>>> pythons
{'Chapman': 'Graham', 'Takada': 'Takashi', 'Atushi': 'Kataoka', 'Palin': 'Michael'}
>>> pythons["Gilliam"] = "Gerry"
>>> pythons
{'Chapman': 'Graham', 'Takada': 'Takashi', 'Atushi': 'Kataoka', 'Palin': 'Michael', 'Gilliam': 'Gerry'}


#キーを複数使った場合は最後の値が残る。
>>> pythons["Gilliam"] = "Terry"
>>> pythons
{'Chapman': 'Graham', 'Takada': 'Takashi', 'Atushi': 'Kataoka', 'Palin': 'Michael', 'Gilliam': 'Terry'}

#"Chapman"というキーに"Graham"を代入してから、"Tatuo"に置き換えている。
>>> some_pythons = {
... "Chapman":"Graham",
... "Takada":"Takashi",
... "Palin":"Michael",
... "Chapman":"Tatuo",
... }
>>> some_pythons
{'Chapman': 'Tatuo', 'Takada': 'Takashi', 'Palin': 'Michael'}

```

##3.4.4 update()による辞書の結合
update()関数を使えば辞書のキーと値を別の辞書にコピーすることができる。

```py
>>> pythons = {
... "Chapman":"Graham",
... "Takada":"Takashi",
... "Palin":"Michael",
... "Atushi":"Kataoka",
... }
>>> pythons
{'Chapman': 'Graham', 'Takada': 'Takashi', 'Palin': 'Michael', 'Atushi': 'Kataoka'}

#第二の辞書が第一の辞書に含まれているのと同じキーを持っていた場合、第二の辞書の値が残る。
>>> others = {"Marx":"Gerge",'Takada': 'Takakakakakkakka'}
>>> pythons.update(others)
>>> pythons
{'Chapman': 'Graham', 'Takada': 'Takakakakakkakka', 'Palin': 'Michael', 'Atushi': 'Kataoka', 'Marx': 'Gerge', 'Howard': 'Moe'}

```

##3.4.5 delによる指定したキーを持つ要素の削除

```py

>>> del pythons["Marx"]
>>> pythons
{'Chapman': 'Graham', 'Takada': 'Takakakakakkakka', 'Palin': 'Michael', 'Atushi': 'Kataoka', 'Howard': 'Moe'}

```

##3.4.6 clear()による全ての要素の削除
辞書から全てのキーと値を削除するにはclear()を使うか、空辞書{}を辞書名に代入すれば良い。

```py
>>> pythons.clear()
>>> pythons
{}

>>> pythons = {}
>>> pythons
{}

```

##3.4.7 inを使ったことキーの有無のテスト


```py

>>> pythons = {'Chapman': 'Graham', 'Takada': 'Takashi', 'Palin': 'Michael', 'Atushi': 'Kataoka', 'Marx': 'Gerge', 'Howard': 'Moe'}

#"key" in "辞書名" の文法
>>> "Chapman" in pythons 
True
>>> "Chaaaaan" in pythons
False

```

##3.4.8 [key]による要素の取得
辞書とキーを指定して、対応する値をとりだす。

```py
>>> pythons = {'Chapman': 'Graham', 'Takada': 'Takashi', 'Palin': 'Michael', 'Atushi': 'Kataoka', 'Marx': 'Gerge', 'Howard': 'Moe'}
>>> pythons["Howard"]
'Moe'

#キーが辞書になければ例外発生
>>> pythons["Howaaa"]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'Howaaa'

#例外を避けるためにあらかじめキーが存在しているか確認する方法3選

#in を使う
>>> "Howaaa" in pythons
False  

#辞書専用のget()関数を使う 辞書、キー、オプション値を渡す
#キーがあればその値を返す
>>> pythons.get("Marx")
'Gerge'

#キーがなければ指定したオプション値が返される。(第二引数)
>>> pythons.get("Howaaa","Not a Python")
'Not a Python'

#オプションをしてしなければNoneになる
>>> pythons.get("Howaaa")

```

##3.4.9 keys()による全てのキー取得
keys()を使えば辞書の全てのキーを取得できる。
Python3ではvalues()やitems()の戻り値を通常のPythonリストにしたい時にもlist()関数を使う必要あり。

```py
>>> signals = {"green":"go","yellow":"go faster","red":"smile for the camera"}
#辞書の全てのキーを取得する
>>> signals.keys()
dict_keys(['green', 'yellow', 'red'])

```

##3.4.10 values()による全ての値の取得

```py

#辞書の全ての値を取得するにはvalues()を使う
>>> list(signals.values())
['go', 'go faster', 'smile for the camera']

```

##3.4.11 items()による全てのキー/値ペアの取得 

```py

#辞書から全てのキー/値ペアを取り出したい場合、items()関数を使う
>>> list(signals.items())
[('green', 'go'), ('yellow', 'go faster'), ('red', 'smile for the camera')]

```

##3.4.12 =による代入とcopy()によるコピー
リストの場合と同様に辞書に変更を加えるとその辞書を参照している全ての名前に影響が及ぶ。


```py

#save_signalsも同じオブジェクトを参照しているため影響を受ける
>>> signals = {"green":"go","yellow":"go faster","red":"smile for the camera"}
>>> save_signals = signals
>>> signals["blue"]="confuse everyone"
>>> save_signals
{'green': 'go', 'yellow': 'go faster', 'red': 'smile for the camera', 'blue': 'confuse everyone'}
>>> signals
{'green': 'go', 'yellow': 'go faster', 'red': 'smile for the camera', 'blue': 'confuse everyone'}

#別の辞書にキー/値をコピーしたい場合copy()を使う。
>>> signals = {"green":"go","yellow":"go faster","red":"smile for the camera"}
>>> original_signals = signals.copy()
>>> signals["blue"]="confuse everyone"
>>> signals
{'green': 'go', 'yellow': 'go faster', 'red': 'smile for the camera', 'blue': 'confuse everyone'}
#影響を受けていない
>>> original_signals
{'green': 'go', 'yellow': 'go faster', 'red': 'smile for the camera'}

```

#3.5 集合
集合は値を放り出してキーだけを残した辞書のようなもの。
キーに値をとして追加したい場合は辞書を使う。

##3.5.1 set()による作成
集合を作るときはset()関数を使うか、1個以上のカンマ区切りの値を{}で囲んで代入する。

```py
#空集合をは要素がない集合
>>> empty_set = set()
>>> empty_set
set()

>>> even_numbers = {0,2,4,6,8}
>>> even_numbers
{0, 2, 4, 6, 8}

```

##3.5.2 set()による他のデータ型から集合への変換
リスト、文字列、タプル、辞書から重複する値を取り除けば集合を作れる。

```py

#"t","e"が重複しているが集合には一つずつしか含まれていない。
>>> set("letters")
{'l', 's', 't', 'r', 'e'}

#リストから集合を作成
>>> set(["Danger","Dancer","Prancer","Mason-Dixon"])
{'Mason-Dixon', 'Danger', 'Prancer', 'Dancer'}

#タプルから集合を作成
>>> set(("Ummaguma","Echoes","Atom Heart Mother"))
{'Echoes', 'Ummaguma', 'Atom Heart Mother'}

#set()に辞書を渡すとキーだけが使われる。
>>> set({'apple':"red", 'orange':"orange", 'cherry':"red"})
{'apple', 'orange', 'cherry'}

```

##3.5.3 inを使った値の有無のテスト

```py

#集合と辞書はどちらも{}で囲まれているが集合はただのシーケンスになっているのに対し、辞書はkey:valueペアのシーケンスになっている。
>>> drinks = {
... "martini":{"vodka","vermouth"},
... "black russian":{"vodka","kahlua"},
... "manhattan":{"cream","kahlua","vodka"},
... "white russian":{"rye","vermouth","bitters"},
... "screwdriver":{"orange juice","vodka"}
... }

#辞書drinksからkey/valueのペアを順に取り出し、それぞれname/contentsに代入し、contentsに"vodka"を含むキーの値を出力している。
>>> for name,contents in drinks.items():
...  if "vodka" in contents:
...   print(name)
... 
martini
black russian
manhattan
screwdriver

#辞書drinksからkey/valueのペアを順に取り出し、それぞれname/contentsに代入し、contentsに"vodka"を含んでいて"vermouth"もしくは"cream"を含まないキーの値を出力している。
>>> for name,contents in drinks.items():
...  if "vodka" in contents and not ("vermouth" in contents or
...     "cream" in contents):
...      print(name)
... 
black russian
screwdriver

```

##3.5.4 組み合わせを演算
&演算子の結果は両方の集合に含まれている全ての要素を格納する集合。

```py

#contentsに"vermouth"、"orange juice"の両方含まれていなければ&演算子は空集合{}を返す。
>>> for name,contents in drinks.items():
...  if contents & {"vermouth","orange juice"}:
...   print(name)
... 
martini
white russian
screwdriver

```

```py

#3.5.3一番下のコード書き換え
>>> for name,contents in drinks.items():
...     if "vodka" in contents and not contents & {"vermouth","cream"}:
...         print(name)
... 
black russian
screwdriver
```

```py

#全ての集合演算子を見ていく

>>> bruss = drinks["black russian"]
>>> wruss = drinks["white russian"]
>>> a={1,2}
>>> b={2,3}

#積集合：&もしくはintersection()関数を使う
>>> a & b
{2}
>>> a.intersection(b)
{2}
>>> bruss & wruss
set()

#和集合：|もしくはunion()関数を使う
>>> a | b
{1, 2, 3}
>>> a.union(b)
{1, 2, 3}
>>> bruss | wruss
{'cream', 'kahlua', 'vodka'}

#差集合：-もしくはdifference()関数を使う。(第一集合には含まれているものの第二集合には含まれていない要素の集合)
>>> a-b
{1}
>>> a.difference(b)
{1}
>>> bruss-wruss
set()
>>> wruss-bruss
{'cream'}

#排他的OR：^もしくはsymmetric_difference()関数を使う（どちらか一方に含まれている要素）
>>> a ^ b
{1, 3}
>>> a.symmetric_difference(b)
{1, 3}
>>> bruss^wruss
{'cream'}

#部分集合（サブセット）：<=かissubset()を使う。
>>> a <=b
False
>>> a.issubset(b)
False
>>> bruss<=wruss
True
#どの集合でも自分自身の部分集合になっている。
>>> a<=a
True
>>> a.issubset(a)
True

#第一の集合が第二の集合の真部分集合になっているかどうか。
#第二の集合が第一の集合の全ての要素に加えて別の要素のを持っていなければならない。<で計算できる。
>>> a < b
False
>>> a<a
False
>>> bruss<wruss
True

#上位集合：部分集合の逆で第二の集合の全ての要素が第一の集合の要素にもなっている関係。
# >=もしくはis superset()関数で調べる。
>>> a>=b
False
>>> a.issubset(b)
False
>>> wruss >= bruss
True
#全ての集合は自分自身の上位集合である。
>>> a>=a
True
>>> a.issuperset(a)
True

#真上位集合：第一の集合に第二の集合の全ての要素とその他の要素が含まれているかどうか
>>> a > b
False
>>> wruss > bruss
True
#集合は自分自身の真上位集合ではない
>>> a>a
False

```

#3.6 データ構造の比較
- リストは角括弧[]
- タプルはカンマ
- 辞書と集合は{}

でそれぞれ表す

また参照の仕方は以下の通り。
- リストとタプルの場合、角括弧の中に入れる数値はオフセット
- 辞書の場合、キー

```py

>>> marx_list=["akagi","Takasuka","Syuda"]
>>> marx_tuple="akagi","Takasuka","Syuda"
>>> marx_dict={"akagi","Takasuka","Syuda"}
>>> marx_list=[2]
>>> marx_list=["akagi","Takasuka","Syuda"]
>>> marx_list[2]
'Syuda'
>>> marx_tuple[2]
'Syuda'
>>> marx_dict={"akagi":"banjo","Takasuka":"help","Syuda":"harp"}
>>> marx_dict["Syuda"]
'harp'

```

#3.7 もっと大きいデータ構造

```py

>>> marxs=["akagi","Takasuka","Syuda"]
>>> pythons=["Gilliam","Cleese","Gilliam"] 
>>> stooges=["Moe","Curly","Larry"]

#個々のリストからタプル作成
>>> tuple_of_lists=marxs,pythons,stooges
>>> tuple_of_lists
(['akagi', 'Takasuka', 'Syuda'], ['Gilliam', 'Cleese', 'Gilliam'], ['Moe', 'Curly', 'Larry'])

#リストを含むリスト作成
>>> list_of_lists=[marxs,pythons,stooges]
>>> list_of_lists
[['akagi', 'Takasuka', 'Syuda'], ['Gilliam', 'Cleese', 'Gilliam'], ['Moe', 'Curly', 'Larry']]

#リストの辞書を作成
#辞書のキーはイミュータブルでなければならないためリスト、辞書、集合は他の辞書のキーになれない。
>>> dict_of_lists ={"Marxes":marxes,"Pythons":pythons,"Stooges":stooges}
>>> dict_of_lists
{'Marxes': ['Groucho', 'Choico', 'Haapo'], 'Pythons': ['Gilliam', 'Cleese', 'Gilliam'], 'Stooges': ['Moe', 'Curly', 'Larry']}

#辞書のキーはイミュータブルでなければならないためリスト、辞書、集合は他の辞書のキーになれないが、タプルはキーになれる。
>>> houses={
... (44.79,-43.55,373):"My House"}

```

#復習課題


##演習 3-1 誕生年から5歳の誕生日を迎えるまでの各年を順に並べてyears_listというリストを作ろう。
```py
>>> years_list=[1994,1995,1996,1997,1998,1999]

```

##演習 3-2 years_listの要素で3歳の誕生日を迎えた年はどれか。

```py

#オフセットは0から始まることに注意
>>> years_list[4]
1998
```

##演習 3-3 years_listに含まれている年の中で最も年長だったのはどれ？
```py

#オフセット-1でとして指定することで右端を選択可能
>>> years_list[-1]
1999

```

##演習 3-4 "mozzarella","cinderella","salmonella"の3つの文字列を要素としてthingsというリストを作ろう。
```py
>>> things=["mozzarella","cinderella","salmonella"]
>>> things
['mozzarella', 'cinderella', 'salmonella']

```

##演習 3-5 thingsの要素で人間を参照している文字列の先頭文字を大文字にしてリスト表示する。
```py
#capitalize()関数で文字列の先頭文字を大文字にする。
>>> things[1]=things[1].capitalize()
>>> things
['mozzarella', 'Cinderella', 'salmonella']

```

##演習 3-6 thingsの中で病気に関する要素を全て大文字にしよう。

```py
#upper()関数で要素の文字列を全て大文字にする。
>>> things[2]=things[2].upper()
>>> things
['mozzarella', 'Cinderella', 'SALMONELLA']

```

##演習 3-7 病気に関する要素を削除し、表示しよう。

```py

#del で要素を削除できる
>>> del things[2]
>>> things
['mozzarella', 'Cinderella']

```

##演習 3-8 "Groucho","Chico","Harpo"を要素としてsurpriseというリストを作成しよう。

```py
>>> surprize=["Groucho","Chico","Harpo"]
>>> surprize
['Groucho', 'Chico', 'Harpo']

```

##演習 3-9 surpriseリストの最後の要素を小文字にして逆順にしてから、先頭文字を大文字に戻そう。

```py
#最後の文字列を全て小文字にする。
>>> surprize[2]=surprize[2].lower()

#最後の要素を逆順にして代入
>>> surprize[2]=surprize[-1][::-1]

#最後の要素の先頭文字を大文字にする。
>>> surprize[2]=surprize[2].capitalize()
>>> surprize[2]
'Oprah'
```

##演習 3-10 e2fという英仏辞書を作り、表示しよう。

```py
>>> e2f={"dog":"chien","cat":"chat","walrus":"morse"}
>>> e2f
{'dog': 'chien', 'cat': 'chat', 'walrus': 'morse'}

```

##演習 3-11　e2fを使ってwalrusという単語に対するフランス語を表示しよう。

```py
#キーである"walrus"を指定して値を表示させる
>>> e2f["walrus"]
'morse'

```

##演習 3-12 e2fからf2eという仏英辞書を作ろう。items()を使うこと。
```py

#f2eの初期化を忘れない
>>> f2e={}

#items()を使ってキーと値をそれぞれenglish,frenchに格納
>>> for english,french in e2f.items():
...  f2e[french] = english
... 
>>> f2e
{'chien': 'dog', 'chat': 'cat', 'morse': 'walrus'}

```

##演習 3-13 f2eを使ってフランス語のchienに対する英語を表示しよう。

```py

#キーである"chien"を指定して値を表示させる
>>> f2e["chien"]
'dog'

```

##演習 3-14 e2fのキーから英単語の集合を作って表示しよう。
```py

#集合作成はset()を使用する。
>>> set(e2f.keys())
{'walrus', 'dog', 'cat'}

```

##演習 3-15 lifeという多重レベルの辞書を作ろう。最上位のキーとしては"animals","other","plants"という文字列を使う。animalsキーは、"cats","octpi","emus"というキーを持つ他の辞書を参照するようにする。"cats"キーは、"Henry","Grumpy","Lucy"という文字列のリストを参照するようにする。他のキーは全て空辞書を参照するようにする。

```py

>>> life={"animals":{"cats":["Henry","Grumpy","Lucy"],"octpi":{},"emus":{}},"plants":{},"other":{}}

```

##演習 3-16 lifeの最上位キーを表示しよう。

```py

#key()を使い多重辞書lifeのキーを表示させている
>>> print(life.keys())
dict_keys(['animals', 'plants', 'other'])

```

##演習 3-17 life["animals"]のキーを表示しよう。

```py

#key()を使い多重辞書llife["animals"]のキーを表示させている
>>> print(life["animals"].keys())
dict_keys(['cats', 'octpi', 'emus'])

```

##演習 3-18 life["animals"]["cats"]の値を表示しよう。
```py

#多重辞書life["animals"]["cats"]の値を表示させている
>>> print(life["animals"]["cats"])
['Henry', 'Grumpy', 'Lucy']

```

#感想
今まで実行文の横にコメント分を記載していたが振り返る時にとても見にくいことが判明した。実行文の上に記載することで見やすくなったので今までのやつも修正しよう。


######参考文献
「Bill Lubanovic著 『入門 Python3』(オライリージャパン発行)」