Python boot camp by Dr.Angela day16

#オブジェクト指向プログラミング (=OOP)

|Object (=実体)||Class (=鋳型)|
|:-:|:-:|:-:|
|car|.|CarBluePrint|
↑ Blueprint(鋳型)からオブジェクト(実体)を生成し、
↓ Class内で関連付けられたメソッド(関数等)を呼び出す。

|Object||Attribute (=どんな性質を持っているか)|
|:-:|:-:|:-:|
|car|.|speed|
|__Object__||__Method (=どんな処理をするか)__|
|car|.|drive( )
__メソッドの呼び出し方とすべてを配置するロジック__がキモ。

###★Pythonでの書き方のお作法

```python:通例
class SomethingSample:

  subject_name1 = math            #Attribute定義
  subject_name2 = biology

  def test(self):                 #Method定義
    print("This is a test")

something = SomethingSample()            #BluePrintからObject「something」を生成
my_favorite = something.subject_name1    #class内で紐づいているAttributeを呼び出し、変数に格納
my_dislike = something.subject_name2
something.test                           #class内で紐づいているMethodを呼び出す                  
print(f"My favorite subject:{my_favorite}\nMy dislike subject:{my_dislike}")
#新しく格納した変数をprintする。("\n"は改行を表す)

#出力結果
This is a test                    #test関数(=method)はThis is a testをprintする
My favorite subject: math
My dislike subject: biology
```
・class名は各wordの頭文字を大文字にする。複数単語が組み合わさっている場合でも各単語の先頭を大文字に。
・classとmethodの間は複数行空けて見やすくする
・methodの引数が1つの場合はselfを記述する

#Mission>> Turtle graphics
kids向けのプログラミング教材としてpythonには__"Turtle"__というライブラリが用意されている。今回はそれをちょっといじってclass作成に慣れてみよう。
Documentはこちら→ https://docs.python.org/ja/3/library/turtle.html

```python:turtle.py
from turtle import Turtle, Screen
import random

timmy = Turtle()           #オブジェクトの名前は"Timmy"
timmy.shape("turtle")      #オブジェクトの形はカメに。他にも矢印等いろいろある。
timmy.home()               #ホームポジション(0,0)に設定
timmy.circle(120,180)      #(distance,angle)だったかな...? 詳細はdocument参照のこと。
timmy.left(90)
timmy.goto(0,0)

l = list(range(0,200))     #0から200までの範囲の中
c = ["green","red","blue","pink","black","grey","white"]
for i in range(50):        #ランダムで50回繰り返す
    x = random.choice(l)   #X座標にリストlからランダムチョイスした値を指定
    y = random.choice(l)   #Y座標にも同様に
    a = random.choice(c)
    b = random.choice(c)
    timmy.color(a,b)       #(線の色,中身の色)
    timmy.penup()          #penを用紙から上げて描線しないようにする
    timmy.speed(8)
    timmy.left(45)
    timmy.setpos(x,y)      #setpos = set_position
    timmy.stamp()

my_screen = Screen()
print(my_screen.canvheight)
my_screen.exitonclick()  
```

出力結果
![キャプチャ2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/975449/8b110224-a95a-589d-6b0a-5c782f0403d1.png)
↑ 最初黒いカメが半弧を描いて下まで行って...
![キャプチャ0.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/975449/36d5ca88-c2e9-5892-045f-3e292812e4fe.png)
↑ カラフルで様々な向きのカメが増殖!!

#Mission>> Virtual Starbucks Machine (OOPver.)
今回はオブジェクト指向で書いてみよう！というチャレンジ。
用いているclassはすでに作られたものである。工夫した点としては、以下の2点。
・材料がなかった場合__店員を呼んで補充するかどうか聞く__
・class Art: を呼び出し、ASCIIアートで100%bar表示をさせる
メイン関数は以下の通り。

```python3:main.py
from menu import Menu, MenuItem
from coffee_maker import CoffeeMaker
from money_machine import MoneyMachine
from art import ART
import time

money_machine = MoneyMachine()
coffee_maker = CoffeeMaker()
menu = Menu()
Turn_on = True

while Turn_on:
    menu_list = menu.get_items()
    order_name = input(f"Which drink?? [{menu_list}]: ")
    if order_name == "report":
        coffee_maker.report()
        money_machine.report()
    elif order_name == "end":
        Turn_on = False
        break
    else:
        drink = menu.find_drink(order_name)
        if coffee_maker.is_resource_sufficient(drink):
            if money_machine.make_payment(drink.cost):
                coffee_maker.make_coffee(drink)
        else:
            restore = input("Do you want to call a staff and restore? [y/n]: ")
            if restore == "y":
                art = Art()
                art.logo()
                coffee_maker = CoffeeMaker()   #繰り返す前に初期化
                menu = Menu()                  #繰り返す前に初期化

```

###★プログレスバーをターミナル出力したい！！
→ 参考：https://dot-blog.jp/news/python-print-overwrite-output/

```python:art.py
class Art:

    def logo(self):
        import time

        print("\nOK.Please wait a minute.")
        time.sleep(1)                        #表示をdelayさせることが可能
        line = "----------------------------"
        print(f"{line}\nReplenishment in progress...")
        pro_size = 10
        for i in range(1, pro_size + 1):     #range(start,finish)
            pro_bar = ("=" * i) + (" " * (pro_size - i))
            print("\r[{0}] {1}%".format(pro_bar, i / pro_size * 100.), end = "")
            time.sleep(0.5)
        print(f"\n{line}")
        time.sleep(1)
        print("\nNow, replinishment completed.")
        time.sleep(1)
```
★process bar自体は以下のように作成している。例えば10%のとき・・・
__1 × "="__ + __(10-1) * " "(スペース)__
進んだ分^^^^^残りの分^^^^^
★process barの出力に関しては以下の通り。
"\r[{0}] {1}%".format(pro_bar, i / pro_size * 100.), end = ""
>"\r"は__キャリッジリターン__といい、コマンド入力のカーソルを先頭に指定する。行末の表示文字列をデフォルトの改行文字"\n"から何もなし" "に指定することで自動的に改行されなくなる。[引用改変]

####.format (置換メソッド)
文字列中に記述する置換フィールドは波括弧 {} の中に書式指定文字列を記述する。
★置換フィールドに数値を指定する
>文字列中に複数の置換フィールドがある場合、それぞれの置換フィールドには区別するために数値かキーワードを指定します。数値を使用する場合は、 0 , 1 , 2 , ... と順番に数値を指定していきますが、どの置換フィールドにどの数値を割り当てるのかは自由です。format メソッドの引数に置換フィールド 0 から順に値を指定していきます。 3 つの置換フィールドがある場合は format メソッドの引数に 3 つの値を指定してください。最初の引数が置換フィールド 0 に渡す値、次の引数が置換フィールド 1 に渡す値、最後の引数が置換フィールド 2 に渡す値です。

>"名前{0}です。{1}歳。住所は{2}です。".format("Yamada", 18, "Tokyo")
"名前{2}です。{0}歳。住所は{1}です。".format(18, "Tokyo", "Yamada")
文字列中の置換フィールドに先頭から順番に 0 , 1 , 2, ... と割り当てる場合には数値を省略することができます。その為、以下 2 つは同じ挙動を示します。

>"名前{0}です。{1}歳。住所は{2}です。".format("Yamada", 18, "Tokyo")
"名前{}です。{}歳。住所は{}です。".format("Yamada", 18, "Tokyo")
[引用(改変)] https://www.javadrive.jp/python/string/index24.html#section1

以上より
__"\r[{0}] {1}%".format(pro_bar, i / pro_size * 100.)__は
{0}にpro_barを置換、{1}にi / pro_size * 100を置換する(.format)ということをしている。

出力結果
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/975449/b37b67ab-2968-aec7-6edb-f8aec012bb6b.png)