Python　初心者の自分用メモ日記r1

##実行環境
* MacBook Air (11-inch, Mid 2012)
* JupyterLab (from Anaconda)
* Python 3.6.4

##前回までのあらすじ
pythonの勉強をはじめたoppasiri330。公式ドキュメントから学ぶぜ！とでかい目標を立てるも、文字数力100万overにあえなく撃沈。心は７つに砕け散った。ついでにpythonに飽きる。

~「世界はヒーローを求めている。」の広告にひかれ、ヒーロー業を始めてから、3ヶ月が経った~

Xday（5月27日)、redditはpythonのアプデに包まれた。oppasiri330は決意する。ヒーロー業は金にならない。再起動のときは来た。I'm back.
ときは七夕7/7。彦星と織姫の慈悲により過去の記憶を取り戻しつつあるoppasiri330。復習を胸に魔物ひしめくQiitaに再び降り立つことを決意する。


##現状：ざっとまとめ

* Dive into Pythonはすぱっと切った。楽しくないねん
* 公式ドキュメントもチュートリアルはあるとはいえ、１から読むのはやめた。おもろないねん。
* checkIOは一時休止した。理由はないねん。
* 3ヶ月間でpythonは全部忘れた。上書き保存だ。
* 学び直した
* 過去記事は見るに耐えない。まぁこいつもいずれそうなる。

##再起動からやったこと：
###TicTacToe ○☓ゲーム。その1
```py

from IPython.display import clear_output

def board(lst = list(range(11))):
    #clear_output()
    print(f"{lst[1]:^3}|{lst[2]:^3}|{lst[3]:^3}")
    print("-"*11)
    print(f"{lst[4]:^3}|{lst[5]:^3}|{lst[6]:^3}")
    print("-"*11)
    print(f"{lst[7]:^3}|{lst[8]:^3}|{lst[9]:^3}")
    
#勝利判定
def win_check(p, lst):
    #lst = [0,1,2,3,4,5,6,7,8,9]
    if lst[1]==lst[2]==lst[3]==p or\
        lst[4]==lst[5]==lst[6]==p or\
        lst[7]==lst[8]==lst[9]==p or\
        lst[1]==lst[4]==lst[7]==p or\
        lst[2]==lst[5]==lst[8]==p or\
        lst[3]==lst[6]==lst[9]==p or\
        lst[1]==lst[5]==lst[9]==p or\
        lst[3]==lst[5]==lst[7]==p:
        return True
    else:
        return False

#引き分け判定
def tie(lst):
    return "" not in lst[1:]

def make_player():
    p1 = ""
    p2 = ""
    while p1.lower() != "o" and p1.lower() != "x":
        p1 = input("Player1, Choose o or x?: ")
    else:
        p2 = "x" if p1.lower() == "o" else "o"
    return p1, p2 
```

```py
from random import *
from IPython.display import clear_output

while True:

    p1, p2 = make_player()

    turn_p1 = randint(0,1)
    if turn_p1:
        print("Player1 is first")
        turn_p1 = True
    else:
        print("Player2 is first")
        turn_p1 = False
    board()
    lst = [""]*10

    while True:

        while turn_p1:
            try:
                idx = int(input(f"Player1,{p1} Choose postion 1-9: "))
            except:
                print("Number please")
                continue
            else:
                if 1<=idx<=9:
                    if lst[idx] == "":
                        turn_p1 = False
                        lst[idx] = p1
                        board(lst)
                    else:
                        print(f"Position {idx} is already choosen")
                else:
                    print("Type between 1-9")

        if win_check(p1, lst):
            print("Player1 Win")
            break
        elif tie(lst):
            print("Draw")
            break


        while not turn_p1: 
            try:
                idx = int(input(f"Player2,{p2} Choose postion 1-9: "))
            except:
                print("Number please")
                continue
            else:
                if 1<=idx<=9:
                    if lst[idx] == "":
                        turn_p1 = True
                        lst[idx] = p2
                        board(lst)
                    else:
                        print(f"Position {idx} is already choosen")
                else:
                    print("Type between 1-9")
        
        if win_check(p2, lst):
            print("Player2 Win")
            break
        elif tie(lst):
            print("Draw")
            break

    if input("Play Again? y or n?: ").lower()[0] != "y":
        print("Thank you for playing")
        break
```

1. 1ヶ月前のコード。うん。過去の記録大事。

###TicTacToeその２　

```py
#display, lst→which number you can type, lst2=real board
def board(lst = list(range(11)), lst2 = [""]*10):
    print(f"{lst[1]:^3}|{lst[2]:^3}|{lst[3]:^3}     " + f"{lst2[1]:^3}|{lst2[2]:^3}|{lst2[3]:^3}")
    print("-"*11+"     "+"-"*11)
    print(f"{lst[4]:^3}|{lst[5]:^3}|{lst[6]:^3}     " + f"{lst2[4]:^3}|{lst2[5]:^3}|{lst2[6]:^3}")
    print("-"*11+"     "+"-"*11)
    print(f"{lst[7]:^3}|{lst[8]:^3}|{lst[9]:^3}     " + f"{lst2[7]:^3}|{lst2[8]:^3}|{lst2[9]:^3}")

from random import choice, randint
def player1():
    return choice([1,-1])
#1なら先行。-1なら後攻。

#True→p1, Flase→p2 first
def first_turn(p1):
    print(f"Player1 is {player[p1]}")
    print(f"Player2 is {player[p1*-1]}")
    return "Player1 is first" if p1 == 1 else "Player2 is first"

#show turn
def show_turn(p1):
    return f"Player1 {player[p1]} turn" if p1 == 1 else f"Player2 {player[p1]} turn"

#type number
def type_number(player,lst,lst2):
    while True:
        try:
            idx = int(input("Type number 1-9: "))
        except:
            print("Oh my god")
        else:
            if 1<=idx<=9:
                if lst[idx] == idx:
                    return idx
                else:
                    print(f"{idx} is Marked number")
            print("Only 1-9")

def change_list(p1, idx,lst,lst2):
    lst[idx] = ""
    lst2[idx] = player[p1]#記号
    return lst, lst2

#勝利判定
def win_check(p, lst):
    #lst = [0,1,2,3,4,5,6,7,8,9]
    if lst[1]==lst[2]==lst[3]==p or\
        lst[4]==lst[5]==lst[6]==p or\
        lst[7]==lst[8]==lst[9]==p or\
        lst[1]==lst[4]==lst[7]==p or\
        lst[2]==lst[5]==lst[8]==p or\
        lst[3]==lst[6]==lst[9]==p or\
        lst[1]==lst[5]==lst[9]==p or\
        lst[3]==lst[5]==lst[7]==p:
        return True
    else:
        return False

#tie
def tie(lst):
    return "" not in lst[1:]


#body
while True:
    lst = list(range(11))
    lst2 = [""]*10
    player = [0, "o", "x"] #toggle

    p1 = player1()
    print(first_turn(p1))
    board(lst, lst2)
    while True:
        print(show_turn(p1))
        idx = type_number(player[p1],lst,lst2)
        lst, lst2 = change_list(p1,idx,lst,lst2)
        board(lst, lst2)

        if win_check(player[p1], lst2):
            print(f"{player[p1]} Win")
            break
        elif tie(lst2):
            print("Tie")
            break
        else:
            p1 = p1*-1
    
    if input("Play again? y or n: ").lower()[0] != "y":
        break

```

1. リスト内部に○と☓を事前に格納。ボードをより見やすく。-1をかけてプレイヤーを切り替え。


##Class


```py

class Book:
#3
    name1="oppasiri"

    def __init__(self, title, author, pages):
        print("A book is created")
        self.title = title
        self.author = author
        self.pages = pages
#1
    def __str__(self):
        return "Title: %s, author: %s, pages: %s" %(self.title, self.author, self.pages)
#2
    def __del__(self):
        print("A book is destroyed")


```
0. `__init__`はクラスのインスタンスを作るとき自動実行される。
1. `__str__`でprint(class_name)したときに表示させる文字列を指定できる
2. `__del__`でclassそれ自体かインスタンスが破壊されたときに、中身が実行される。
3. `self.変数名`でインスタンス変数が作れる。`instance_name.変数名`で参照可能。
3. 上記`name`はクラス変数。インスタンス化しても残る。`self.変数名`のインスタンス変数と同じように、参照できる。`dir(クラス名orインスタンス名)`とかで確認可能

##lambda

```py
#1
def square(num):
    return num**2

def square(num): return num**2 #同じ

lambda num: num**2

#2
f = square
```
1. 全部等価。
2. 関数名はあくまで目盛の保存場所。別の変数名に保存可能

##Scope
ざっくりいうと変数の影響範囲。

* L:Local
* E:Enclosing function locals
* G:global
* B:Built-in
がある。詳しくはLEGB rulesへ。おれは読んでない。

ざっくりいうと、
localはglobalでない変数。
Enclosing function localsはdefとかで定義された関数の中で、また定義された別の関数からみたlocal変数のこと。
globalは最上位階層にいる変数。定義された関数の外で変数つくったらglobal。
Built-inは、予約語全般。あとexception, Error群, module名など。すでに使われてる言葉群。


```py
#local, Enclosing function local
name = "This name is Global"

def func():
    
    name = "John"
    
    def func2():
        
        print("Hello " + name)
    
    func2()


func()
>>>Hello John
```
1. 同じ階層に明示された変数がない場合。変数を探しに1つずつ階層を遡る。
2. `func()`の中の`name`はlocal変数。
3. `func2()`からみたら`func()`の`name`はEnclosing function local変数。


```py
name = "This name is Global"

def func():
    
    #name = "John"
    
    def func2():
        
        print("Hello " + name)
    
    func2()

func()
>>.Hello This name is Global
```
1. 1つ上の階層にないからglobalまで遡ってる


```py
#local 
x = 50
def func():
    x = 2
    print(x)

func()
>>>2
print(x)
>>>50
```
1. `global`と明示しないかぎり、ローカル変数はグローバル変数に影響を与えない。

```py
#global keyword
x = 50
def func():
    global x
    print("Now this x is global: ", x)
    x = 2

print(x)
>>>50
func()
>>>Now this x is global: 50
print(x)
>>>2

#2
global x, y, z
```
1. `global`キーワードを宣言すれば、global変数を作成できる。
2. 複数のグローバル変数を宣言することもできる。


###`__name__`と`__main__`

```py
if __name__=="__main__":
    #動作
    pass
```
0. `__name__`はどのファイルにも自動で作られるattribute(属性)。変数みたいなもの。`.py`の拡張子でファイルをつくれば自動的に生える。
1. .pyファイルを実行すると、その.pyファイルにおいて、`__name__`には`__main__`という文字列が自動的に保存される。つまりif節の中身が実行される。

```py
#a.py
#b.py
#上記2つのファイルが存在する場合。

#a.py上で
import b

if __name__=="__main__":
    #動作
    pass
```
1. `python a.py`でa.pyを実行すると、a.pyの`__name__`には`__main__`という文字列が格納される。b.pyの`__name__`には別の文字列が保存される。
2. b.pyの属性`__name__`は`__main__`という文字列ではないため。b.pyでは動作部分が実行されない
3. importされると、importされたファイル全体(今回は`b.py`)が実行される。実行されると困る動作を`if __name__=="__main__":`にぶちこめばimportされたときに実行されないってこと。


##Error and Exception Handling
`SyntaxError`は(,),:,",コンマ忘れとかそこらへん見直すとなんとかなる。
大抵Errorの行より前に発生してる。



##ひとこと
前回は2週間で飽きたけど。今1ヶ月以上続いてる。湖池屋のうすしお復活した影響はでかい。