python 公式ドキュメントチュートリアル 4.制御フローツール　自分用メモ

##参考元： https://docs.python.jp/3/tutorial/controlflow.html
Pythonチュートリアル。

寄り道：pythonの更新
http://graphbooth.com/2017/05/31/pythonmac.html
https://qiita.com/yoshizaki_kkgk/items/4663148a2b3ca078ddbc　
ここを参考にpython3.4.2から3.6.4に更新をしようと思ったんだ。でも`pyenv global 3.6.4`を使ってもpythonのversioが切り替わらない。pythonシェルを起動しても、python3.4.2にのまま。どゆこっちゃ。
インストールがされてないのかと思って、再インストールしたら(現在2回目)すでに存在するで。と言われる。yで続ける。インストールが始まるのだが…。to be continuted...

```py
URYYYYYYYYYYY:~ badapple330$ pyenv install 3.6.4
pyenv: /Users/badapple330/.pyenv/versions/3.6.4 already exists
continue with installation? (y/N) y
python-build: use openssl from homebrew
python-build: use readline from homebrew
Downloading Python-3.6.4.tar.xz...
-> https://www.python.org/ftp/python/3.6.4/Python-3.6.4.tar.xz
Installing Python-3.6.4...
python-build: use readline from homebrew
Installed Python-3.6.4 to /Users/badapple330/.pyenv/versions/3.6.4

URYYYYYYYYYYY:~ badapple330$ 

URYYYYYYYYYYY:~ badapple330$ pyenv global 3.6.4
URYYYYYYYYYYY:~ badapple330$ python -V
Python 2.7.10

URYYYYYYYYYYY:~ badapple330$ pyenv versions 
  system
* 3.6.4 (set by /Users/badapple330/.pyenv/version)

```
なぞなんだが？
`pyenv versions`で3.6.4は存在してるっぽい。

```py
URYYYYYYYYYYY:~ badapple330$ python --version
Python 2.7.10

URYYYYYYYYYYY:~ badapple330$ pyenv global 3.6.4
URYYYYYYYYYYY:~ badapple330$ python --version
Python 2.7.10

```
はい。
↓
解決編：
~/.bash_profile関連の問題だった。`la -ls`であると思ったらなかった？のか3.4.２にpathが通るよう記述してあった？
https://qiita.com/1000ch/items/93841f76ea52551b6a97
ここの下記を実行すればうまくいった。

```py
$ echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bash_profile
$ echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bash_profile
$ echo 'eval "$(pyenv init -)"' >> ~/.bash_profile
```

`export PATH="$HOME/.pyenv/shims:$PATH"`
を`.bash_profile`のどこに書き込めば良いのか、同保存すれば良いのか最初のURLじゃまったくわからんかったのが原因。無知なの。許して。
python3で3.6.4が起動するようになったから、結果オーラい。

##4. その他の制御フローツール
###4.1 if文
1. pythonではelse ifではなく、`elif`でif文の分岐を行う。

###4.2 for文
1. pythonにおけるfor文は、任意のシーケンスにおいて反復を行う。反復の順序は、シーケンス中に要素が現れる順番。

```py
>>> for w in words:
...  print(w, len(w))
... 
cat 3
fight 5
coming 6
```
イテレータ： iterator: プログラミング言語において、配列やそれに類似する集合的データ構造の各要素に対する繰り返し処理。反復。

```py
>>> for w in words[:]:
...  if len(w) > 4:
...   words.insert(0, w)
... 
>>> words
['coming', 'fight', 'cat', 'fight', 'coming']
```
1. ループの範囲としているシーケンスに対して、何らかの変更を行いたい場合。最初に、スライス[:]によって、コピーを作ると便利。
2. 今現在for文の範囲としてwords[:]を使用。そして、if文の条件が合えば元のリストwordsに対して`insert()`を行っている。もし、for文の範囲にwords[:]ではなく、wordsを使った場合、無限ループしてしまう。

###4.3 range関数
数列に対して反復を行う場合、組み込み関数`range()`が便利。`range(begin_index, end_index, increase_amount)`はend_indexまでの数列を生成する。増加量も指定することができる。

```py
>>> for i in range(5):
...  print(i)
... 
0
1
2
3
4
>>> for i in range(100, 0, -20):
...  print(i)
... 
100
80
60
40
20

>>> print(range(10))
range(0, 10)
>>> list(range(5))
[0, 1, 2, 3, 4]
```
1. 指定した終端値は生成されたシーケンスに含まれない
2. range(5)は５個の値を0から作成する。
3. rangeを0ではなく、別の数から開始できる。負の値も可能。また、増加量も指定できる。
4. あるシーケンスにおいて、indexによって反復を行うには、`range(len(list))`とする。が、`enumerate()`のほうが楽。しかしここでは紹介されてない。

5. `range()`が返すオブジェクトは、リストのように振る舞うがリストではない。イテレート（反復）をしたときのみ、指定された数列を返す。このようなリストではないが、イテレートする際に連続した要素を返すオブジェクトを**イテラブル(iterable)**と呼ぶ。`list()`や`for文`はイテラブルなものからリストを生成する。
例) filter,mapオブジェクトもおそらくイテラブル。
□この５.は初めて知った。ためになる。


###4.4 break文とcontinue文とループのelse節
1. `break`文はC言語と同じく、最も内側のforまたは、whileループを中断する。
2. ループ分は`else`節をもつことができる。forやwhile文で反復処理対象のリストを使い切った時、あるいはwhileの条件が偽になってループを脱出したときに`else`節が実行される。しかし、`break`文でループを終了した時は、`else`節は実行されない
□知らんかった。

```py
>>> for n in range(2,10):
...  for x in range(2, n):
...   if n % x == 0:
...    print(n, "equals", x,"*", n//x)
...    break
...  else:
...   print(n, "is a prime number")
... 
2 is a prime number
3 is a prime number
4 equals 2 * 2
5 is a prime number
6 equals 2 * 3
7 is a prime number
8 equals 2 * 4
9 equals 3 * 3
```
素数(prime number)判定プログラム。

1. 上記の`else`文はifではなく、for節と対応している。`break`がfor文内で実行されずに、ループを終えた場合に`else`節を行う。`break`でループから脱出した場合には、`else`節は実行されない。

```py
>>> for num in range(2,10):
...  if num%2==0:
...   print("Found an even number", num)
...   continue
...  print("Found a number", num)
... 
Found an even number 2
Found a number 3
Found an even number 4
Found a number 5
Found an even number 6
Found a number 7
Found an even number 8
Found a number 9
```
1. `continue`文は実行されると、以降の処理を実行せず、次のループを行う。今回は、if節の中身が実行されれば、if節のそとのprint()は実行されないということ。


###4.5 pass文

```py
>>> while True:
...  pass #処理をやめるには Ctrl+c
... 
 ^CTraceback (most recent call last):
  File "<stdin>", line 2, in <module>
KeyboardInterrupt

>>> class EmptyClass:
...  pass
... 
```

1. `pass`を記述すると何もしない。無限ループの処理はCtrl + Cで強制終了できる。
2. 最小のクラスをつくるさいに`pass`を利用できる。
3. 何か関数を考える時、具体的なコードをかかずにあいまいな状態で実行するのに使える

###4.6 関数を定義する

```py
>>> def fib(n):
...  '''docstring. the explation of function'''
...  a,b = 0,1
...  while a<n:
...   print(a, end=" ")
...   a,b = b, a+b
...  print()
... 
>>> fib(100)
0 1 1 2 3 5 8 13 21 34 55 89 

>>> f = fib ⑤
>>> f(100)
0 1 1 2 3 5 8 13 21 34 55 89 
```
n以下のフィボナッチ数列を定義した関数。
フィボナッチ数列： 次の項の数値は、１つ前の項と２つ前の項の和である数列。
1. `def`は関数の定義を始めるキーワード。`def`の後に、関数名と、（）の中に仮引数を示せし:を記述。それいこうのインデントのされた行が関数の中身になる。
2. 関数の本体の記述する文の最初の行を'''...'''の形のコメントアウトされた文字列にすることができる。このコメントアウトされた部分は`docstring`と呼ばれ、関数の属性として扱われる。どんな関数か誰でも分かるようになるから、記述を推奨される
3. 関数を実行すると、関数の中のローカル変数のために、symbol tableが用意される。関数の中で変数に代入されると、このtableに値が格納される。（変数の値の場所)。そして変数の値を参照しようとすると、現在地点のtableを検索→次にその関数が含まれる外側の関数のtableを参照→グローバルのテーブルを参照→最後に組み込みの名前テーブルを参照と。徐々に遡って変数の値を検索する。ゆえに、グローバルな変数を参照できるが、関数内部でグローバルな変数に値を代入できない（関数の中に、同名の変数が作成される？ってことじゃね）
4. 関数を呼び出す際の実引数は、関数が呼び出された時に関数のローカルなシンボルテーブルに格納される。
5. 関数の定義の際にも、関数名は現在すでに存在するシンボルテーブル内に格納される(作られた関数内部のシンボルテーブルではない）。ゆえに関数を別の変数名に代入することもできる。


```py
>>> print(fib(0))　
None 

>>> def square(n):
...  return n**2
... 
>>> square(6)
36
```
1. 関数は`return`文を持たない関数でも、`None`を返している。
2. 関数を`return`文で単一の値を返すことができる。引数がない場合、関数が終了した場合は`None`が返る。`return`が実行されると、それ以降の処理は実行されない。

###4.7 関数の定義についてもう少し
可変する個数の引数を伴う関数を定義することもできる。
引数の定義方法には３つの形式がある。
####4.7.1 デフォルトの引数値

```py
>>> def ask_ok(prompt, retries=4, reminder="Plase try again"):
...  while True:
...   ok = input(prompt)
...   if ok in ("y","ye","yes"):
...    return True
...   if ok in ("n", "no", "nop", "nope"):
...    return False
...   retries = retries -1
...   if retries < 0:
...    raise ValueError("invalid user response")
...   print(reminder)
... 
```
1. 最初に渡した文字列が表示され、そのあとの入力を行う。入力された値によって分岐するプログラム。while True:で何らかの`return`が返されるまで繰り返す。`return`が実行されれば、それ以降の処理は行われない。
2. この関数は、３つの方法で呼び出せる。
・ 必須の引数のみ与える: ask_ok('Do you really want to quit?')
・ 一つのオプション引数を与える: ask_ok('OK to overwrite the file?', 2)
・ 全ての引数を与える: ask_ok('OK to overwrite the file?', 2, 'Come on, only yes or no!')
3. 仮引数に初期値が指定されている引数は、関数を呼び出す際に省略することもできる。あるいはあらたな値を引数に指定することもできる。
4. この`in`キーワードは、シーケンスが特定の値を含んでいるか調べる。

```py
>>> i = 3
>>> def f(arg=i):
...  print(arg)
... 
>>> i = 100
>>> f()
3
```
1. 仮引数のデフォルト値は、関数が定義されたとき変数を指定した場合、その関数を呼び出した時点に格納されている変数の値が代入される。`scope`と呼ばれる範囲の話。

```py
>>> def f(a, L=[]):
...  L.append(a)
...  return L
... 
>>> print(f(1))
[1]
>>> print(f(2))
[1, 2]
>>> print(f(3))
[1, 2, 3]

def f(a, L=None):
    if L is None:
        L = []
    L.append(a)
    return L
```
1. つまりリストのように、変更可能なオブジェクトの場合。変更を加えれば、関数を呼び出したときごとに初期値が変わる
2. デフォルト値を呼び出すごとに一定にしたい場合は、判定して、毎回リセットすればいい。


####4.7.2 キーワード引数

```py
>>> def kwarg(title, body="a test", conc="finish", type="oppai"):
...  print(title)
...  print(body)
...  print(conc)
...  print(type)
... 
>>> kwarg("siri") #通常
siri
a test
finish
oppai
>>>kwarg(type=1,conc=2,title=0,body="good")②#引数名を指定して代入。順番はバラバラでも良い。
0
good
2
1

>>> kwarg(body=1, "oppai") ③
  File "<stdin>", line 1
SyntaxError: positional argument follows keyword argument
>>> kwarg("oppai", body=1) ④
oppai
1
finish
oppai

>>> kwarg("oppai", title="siri")　⑤
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: kwarg() got multiple values for argument 'title'
```
1. 関数は引数名を指定して、呼び出すこともできる。つかここDive into pythonでやったわ。キーワード引数と呼ぶ。逆に普段通り、引数の順番に値をただ代入することを、位置指定引数と呼ぶ。
2. 引数名をを指定して関数を呼び出せる。この場合引数の順番は関係なくなる。
3. しかし、一度引数名を指定して代入を行った場合、それ以降も引数名を明記する必要がある。
4. 引数名を指定する以前なら、引数名を指定せず直接代入できる。"oppai"はtitleに無事代入された。位置指定引数、キーワード引数の順番はOK。
5. また如何なる引数も、値を複数回受け取れない。

```py
>>> def shop(kind, *argument, **keywords):
...  print("Do you have", kind, "?")
...  print("Im sorry, we're all out of", kind)
...  for arg in argument:
...   print(arg)
...  print("-"*40)
...  for kw in keywords:
...   print(kw, ":",keywords[kw])
... 
>>> shop("burger", "its very runny, sir", "its really very, Very runny, sir", shopkeeper = "Michael Palin", cilent="John Cleese", sketch="cheese shop sketch")
Do you have burger ?
Im sorry, we're all out of burger
its very runny, sir
its really very, Very runny, sir
----------------------------------------
shopkeeper : Michael Palin
cilent : John Cleese
sketch : cheese shop sketch
```
正直言ってこの例わかりにくい。打ちにくいし。

1.　仮引数の最後に`**name`の形式の`**`がついた仮引数があると、それまでの仮引数に対応したものを除いた全てのキーワード引数が入った辞書を受け取る。　
例)
キーワード引数とは： 引数名を宣言しつつ、かつ値も指定すること。
`shop(name = "keyword"): nameという引数名を指定し、"keyword"という値を変数nameに格納している。（実際は、"keyword"という値の変数名がnameだよ。と動くが、それはいまどうでもいい。)
つまり、1の意味を言い換えると。`**name`は関数の仮引数として存在しない新しい引数名とその値を、複数個受けとり辞書にしてくれる。
上記例の
`
shopkeeper : Michael Palin
cilent : John Cleese
sketch : cheese shop sketch
`の　shopkeeper,　client, sketchは仮引数名として存在していない。しかし、最後のfor文で辞書のkeyを受け取り、値を出力している
2.　仮引数の前に`*`がついた`*name`こっちは、引数がすでに存在する仮引数を満たした場合、残りの１つ以上の値をタプルの形で受け取ってくれる。
例でみると、"burger"は引数kindに対応。残りの "its very runny, sir", "its really very, Very runny, sir"が`*arg`の中にタプルの形式で格納されている。格納される順番は、引数の順序と同じ。

```py
>>> def test(*args, sep="/"):
...  return sep.join(args)
... 
>>> test("a","b","c")
'a/b/c'
>>> test("a","b","c", sep=".")
'a.b.c'
```
1. また`*`ついた引数以降、位置指定引数は使えず、キーワード引数のみ使える。キーワード引数で値を変更することができる。

###4.7.4　引数リストの展開。アンパック。
引数がすでにリストやタプルになっていて、位置指定引数のように個別な引数が要求される関数を使う時、リストやタプルを`*`で展開することができる。

```py
>>> list(range(2,8)) ①
[2, 3, 4, 5, 6, 7]
>>> args = [2, 8]
>>> list(range(args))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'list' object cannot be interpreted as an integer
>>> list(range(*args))
[2, 3, 4, 5, 6, 7]
```
1. `range()`はstart, endの値を別に与える場合がある。
2. argsのリストを`range()`の引数に取る場合、リストではだめとエラーが出る。しかし`*`をつけて`*args`と引数に指定すると、リストであるargsが分解されて、リストの要素が１つずつ位置指定引数として関数に代入される。つまり*[2, 8]だと、2が`range()`のstartに、8がendにリストからバラされて代入される。つまり、`range()`関数が無事実行される。

```py
>>> def parrot(voltage, state="a stiff", action="voom"):
...  print("This parrot wouldn't", action, end='　')
...  print("if you put", voltage, "volts through it.", end="　")
...  print("E's", state, "!")
... 
>>> d = {"voltage": "four million", "state": "bleedin' demised", "action": "VOOM"}
>>> parrot(**d)
This parrot wouldn't VOOM　if you put four million volts through it.E's bleedin' demised !
```
1. parrotという作られた関数。変数dは辞書。parrotが呼び出される時、辞書dがキーワード引数の形(例: voltage = "four million")の形でそれぞれ分解される。辞書のkeyがキーワード引数名に、keyの値がキーワード引数の値として分解される。だからparrot引数voltageに、辞書dの"four million"が代入されている。

###4.7.5 ラムダ式 `lambda`
キーワードの`lambda`を使うと、名前のない簡易な関数を生成できる。もちろん、`lambda`で作った関数に名前をつけたり、変数に代入したりもできる。オブジェクトなので。

```py
>>> c  = lambda a, b: a*b
>>> c(10, 55)
550
```
1. `lambda 引数: 返り値`という形式。引数は直接の値でも、変数でも大丈夫。
2. cという変数に`lambda`で作った関数を格納している。その場合,`c()`の形で引数を()の中に入れれば使える

```py
>>> def increment(n):
...  return lambda x:x+n
... 
>>> f = increment(23)
>>> f(0)
23
>>> f(1)
24
```
1. `return`のところで`lambda`式を使っている。関数incrementのｎを指定して、fに代入することで、xを引数に受ける別の関数を作れる。入れ子構造。なんかどっかで使いそう。

```py
>>> pairs = [(1, 'one'), (2, 'two'), (3, 'three'), (4, 'four')]
>>> pairs.sort(key=lambda pair:pair[1])
>>> pairs
[(4, 'four'), (1, 'one'), (3, 'three'), (2, 'two')]
>>> pairs.sort(key=lambda a:a[0])
>>> pairs
[(1, 'one'), (2, 'two'), (3, 'three'), (4, 'four')]

```
1. `sort()`にはキーワード引数`key`がある。keyには、１つの引数をとる関数を指定する。リストのそれぞれの要素から比較するための基準(key)を取り出すためにその関数は使われる。(例えば、 key=str.lowerなら小文字でリストの要素を並び替える)。今回はpair :pair[1]。単純にリストの要素１番めをそれぞれ使って比較するということ。リストの要素のタプルの[1]の要素を参照して、並び替えるということ。小文字のアルファベットが、a-z順に並び替えられた。

###4.7.6 ドキュメンテーション文字列 docstring
docstringはdive into pythonでやった。
関数の名前と引数を宣言して:を打った次の行に、インデントし`"""..."""`の中身を記述すること。
`"""..."""`の中身は、大文字で始まり、`.`で終わる必要がある。
docstring内部で一行以上記述する場合、docstring内部の二行目は空白にする。３行目から続きをかき始める。

```py
>>> def func():
...   '''start of docstring.
...   
...   空白の行が必要。そしてこの行から続きをかく'''
...   pass
... 
>>> print(func.__doc__)
start of docstring.
  
  空白の行が必要。そしてこの行から続きをかく
```
1. `__doc__`で関数のdocstringに触ることができる。


###4.7.7 関数の注釈、アノテーション　annotations
annotations: 注釈

```py
>>> def f(ham: str, eggs: str = 'eggs') -> str:
...     print("Annotations:", f.__annotations__)
...     print("Arguments:", ham, eggs)
...     return ham + ' and ' + eggs
...
>>> f('spam')
Annotations: {'ham': <class 'str'>, 'return': <class 'str'>, 'eggs': <class 'str'>}
Arguments: spam eggs
'spam and eggs'
```
1. チュートリアルの日本語を俺の日本語に翻訳すると。関数を定義する時、仮引数の後ろに`: データ型`と記述する(例えば ham: str)ことで`__annotations__`という関数内部の属性(変数みたいなもの)に、仮引数名とデータ型のセットを辞書に格納できる。関数内部で`return`による具体的戻り値がある場合は引数の()以降に `-> データ型`と記述すれば、戻り値のデータ型も`__annotations__`に格納できる。
2. 仮引数のham, eggsのうしろにそれぞれ`:データ型`。`->`でreturnのデータ型を指定。`関数名.__annotations__`で辞書の形式で保存した仮引数や変数のデータ型の注釈を閲覧できる。

###4.8 コーディングスタイル
読みやすいコードを書くにはどうすればいいか。
pythonには　pep8: https://www.python.org/dev/peps/pep-0008/
と呼ばれる推奨される記述方法がある。

1. インデントには空白 4 つを使い、タブは使わないこと。　まじか。タブすげぇ好きなんだけど…。
理由： 空白 4 つは (深くネストできる) 小さいインデントと (読み易い) 大きいインデントのちょうど中間に当たります。タブは混乱させるので、使わずにおくのが良いです。読みやすいと、たくさん深くできるの中間。

2. ソースコードの幅が 79 文字を越えないように行を折り返すこと。
理由： 小さいディスプレイを使っているユーザも読み易くなり、大きなディスプレイではソースコードファイルを並べることもできるようになります。確かに。でも79行とか分からないよ？

3. 関数やクラスや関数内の大きめのコードブロックの区切りに空行を使うこと。
4. 可能なら、コメントは行に独立で書くこと。　　記述した式と同じ行は推奨されない、と
5. docstringで説明をつけること
6. 演算子の前後とコンマの後には空白を入れ、括弧類のすぐ内側には空白を入れないこと: a = f(1, 2) + g(3, 4)。わかる。
7. クラスや関数に一貫性のある名前を付けること。慣習では CamelCase をクラス名に使い、 lower_case_with_underscores を関数名やメソッド名に使います。常に self をメソッドの第 1 引数の名前 (クラスやメソッドについては クラス初見 を見よ) として使うこと。
camel: ラクダ？
8. あなたのコードを世界中で使ってもらうつもりなら、風変りなエンコーディングは使わないこと。どんな場合でも、Python のデフォルト UTF-8 またはプレーン ASCII が最も上手くいく
9. 同様に、ほんの少しでも他の言語を話す人がコードを読んだりメンテナンスする可能性があるのであれば、非 ASCII 文字も識別子に使うべきではありません。

９個あるじゃねぇか。pep8と8はなんじゃい。


##終わりに
チュートリアルの英語から日本語翻訳されたものを、自分の理解できる言葉に再翻訳しないと頭に入ってことねぇ！
３日更新してないってやべぇよこいつ。時間は有限なんじゃい！！！１。削除の原則削除の原則。
スマホでブラウザのSmoozaを使いはじめてみた。使いこなすまで幾星霜。
中国の技術とかエストニアとか何かすげぇよね。今日郵便局に書留持ってて休みだったのに疲れててふと思った。

女子がパシュートで金メダルとった瞬間泣いたりしてた。
ガラスに指で暗号を書いて、当然一見は何も見えないが、指紋鑑定を行い一人分の指紋だけ浮き上がらせると内容がわかる。みたいなの妄想してたらね…。