Pythonの「p」を知りたい。。defとclass

## 全般
※取り消し線が多数存在しますが悪しからずです※
コメント欄も併せてご覧ください。貴重なご指導いただいています(*'▽')
現在AWS Lambdaを使わせていただいているので、そこで私の好きなPythonを使用する機会をいただき、先輩に怒られないように勉強です。言葉少なめです(-_-;)

## お品書き
- ここだけ読むと概要理解
- def
- class
- 個人的に整理

### ここだけ読むと概要理解
#### 言葉の整理
- オブジェクト（class）
- 属性（attribute）
- メソッド（関数定義）
#### 例え話
あなたはお店をいくつも経営している社長だと仮定しましょう。
お店（オブジェクト）には品物（属性）を陳列し、そこの店員さんは仕入れ（メソッド）て、支払い（メソッド）する必要があります。
#### 少し深く
```
お店(class)
　仕入れる(def)
　支払う(def)
```
ここで大阪店のことですよ。と実体を作ってあげる。
```
お店(class)
　仕入れる(def)
　支払う(def)
 
大阪店 = お店(instance)
```
そして、誰が、何を、いくら欲しているの？
```
お店(class)
　仕入れる(def)
     〇個〇円の〇〇を〇〇が仕入れて。(attribute)
　支払う(def)
     トータルいくらか、誰が何を買ったか出力して。(attribute)
     
大阪店 = お店(店長は、1個100円の、りんごがほしい)(instance)
```
大阪店に対してあなたは言いました。いったい誰が何を仕入れていくらかかったの？
```
お店(class)
　仕入れる(def)
     〇個〇円の〇〇を〇〇が仕入れて。(attribute)
　支払う(def)
     トータルいくらか、何を買ったか出力して。(attribute)
     
大阪店 = お店(店長は、1個100円の、りんごがほしい)(instance)

大阪店.支払う
```
大阪店、店長が1個100円のりんごを1個仕入れました。と答えてくれました。
そしてあなたは、追加でみかんも買って、同じように報告して！と言いました。
```
お店(class)
　仕入れる(def)
     〇個〇円の〇〇を〇〇が仕入れて。(attribute)
     
　支払う(def)
     トータルいくらか、誰が何を買ったか出力して。(attribute)
     
大阪店 = お店(店長は、1個100円の、りんごがほしい)(instance)
大阪店(店員1) = お店(店員1は、1個100円の、みかんがほしい)(instance)

大阪店.支払う
大阪店(店員1).支払う
```
この要領でもっと仕入れよう！とあなたは大阪店の店長に言いました。
大阪店の店長は、東京店も仕入れ状況をモニタリングしていますか？視野が狭いですね社長！とあなたに言ったのです。社長は東京店も同じ要領で東京店の店長に指示しました。

```
お店(class)
　仕入れる(def)
     〇個〇円の〇〇を〇〇が仕入れた(attribute)
     
　支払う(def)
     トータルいくらか、誰が何を買ったか出力して。(attribute)


大阪店 = お店(店長は、1個100円の、りんごがほしい)(instance)
大阪店(店員1) = お店(店員1は、1個100円の、みかんがほしい)(instance)
東京店 = お店(店長は、1個100円の、バナナがほしい)(instance)

大阪店.支払う
大阪店(店員1).支払う
東京店.支払う
```
とういう感じで、より複雑な処理を1セットとして実行できることがclassの良いところ。
名古屋店の追加や他の店舗が追加されようが、instanceを作成することで対応できます。
また、各店舗によって商品の価格が違うといった場合など、部分的にコードを追加することで、何回も処理を記載することなく複雑な算出を実装することができるのです。



### def
>関数定義に使用するキーワード
関数定義によって関数オブジェクトが生成される
関数名()で関数に定義した処理を実行

発展系は次の画像を見てなんとなく理解
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3518951/62975aa0-1641-0056-41c5-d521a6937a58.png)

あとは、returnに追加してみる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3518951/d8e3bfc8-734e-a895-91b5-f09245990083.png)

複数の引数を使った関数定義(def)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3518951/96f7e2fa-f116-641e-6e6f-4abf30e4cab1.png)




### class
>クラス定義に使用するキーワード
クラス定義によってクラスオブジェクトが生成される
クラス名()でインスタンスオブジェクトを生成し、__init__メソッドに定義した処理を実行してインスタンスの初期化を行う

~~お気づきだろうか。。~~
~~数値（引き数）が1つしかない場合はdef関数で済むけど、class関数は多数の数値（引数）を相手にできる。~~


init
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3518951/ea322b5d-350f-a692-ddf1-f9b0d6ec3c0f.png)
手順は、classで初期設定⇒メソッド定義⇒インスタンス作成⇒呼び出し。
組み合わせ(複雑すぎw)。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3518951/fa26155d-caef-2c8b-1f07-c2ffb5bb557a.png)


ここで基本。単発のdefでは、引数は無くても良い。

しかし、classを使用する場合は、defと言わず、”メソッド”という呼び名に変わり、必ず引数が必要となり、引数が必要ないときでも「self」と記載するのが慣習。

返り値なし。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3518951/40f108d2-8c40-c01c-d7b0-9cce330677cd.png)

返り値あり。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3518951/de7cd55c-20ed-2dde-4965-16c9a6de0597.png)


実際に使用できる関数に変更。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3518951/ddf64411-d1ef-ed94-5e8b-60c2c0f7ae49.png)
アトリビュートの使用（関数内の変数と理解）
インスタンス毎にアトリビュートを定義して使用する。
次のとおり"name"が急に定義されている箇所がインスタンス"instance = Student()"に設定されたアトリビュート（変数）ということ。
（インスタンス名がややこしいのは無視で(^^;）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3518951/8606d85b-f7d8-400e-1f55-2a8ffe238f74.png)




~~ここまでを個人的にまとめると、def関を使用したい時は、繰り返し関数を呼びたい時。class関数を使用する際は、関数の引数が多数存在する場合などに使用する。~~

### 個人的に整理
```:def
def Example():
    print("example")
```
呼び出しは、`Example()`
```:def（引数有）
def Example(name):
    print(name + "さん")
```
呼び出しはExample(example)

```:class
class Person():

    def __init__(self,name,nationality,age):
        self.name = name
        self.nationality = nationality
        self.age = age

instance = Person("keiji","japan","100")
```
呼び出し例は、"instance.name"
メソッド内（def）でアトリビュート（変数）を書くことで呼び出しという理解。

```:class（複雑。。。）
class Person():

    def __init__(self,name,nationality,age):
        self.name = name
        self.nationality = nationality
        self.age = age
    def hello(self,name):  # ここではself必須
        print(f"{name} さん、こんばんわ。私の名前は{self.name}です。出身は{self.nationality}で、年齢は{self.age}歳です。")

instance = Person("keiji","japan","50")
```
helloを呼び出してみる。
"instance.hello("taro")"
※全般、【print】によって出力させているが、実際は【return】を使用する。
返り値を取ってくれるので、以降のコードで呼び出しが可能となる。

```:returnをつこてみると。
class Person():
    def __init__(self, name, nationality, age):
        self.name = name
        self.nationality = nationality
        self.age = age

    def hello(self, name):
        return f"{name} さん、こんばんわ。私の名前は{self.name}です。出身は{self.nationality}で、年齢は{self.age}歳です。"

# インスタンス作成
instance = Person("keiji", "Japan", 30)

# helloメソッドの呼び出しと結果を変数に代入
result = instance.hello("keiji")
print(result)  # 結果を表示
```
ここでprintでの出力のままであると、noneが返ってきてしまう。

インスタンスを複数指定！
```
# ここで初期設定
class Person:
    # メソッドを定義
    def __init__(self, name, nationality, age):
        self.name = name
        self.nationality = nationality
        self.age = age

    def hello(self, name):
        print(f"こんばんわ{name}さん、私は{self.name}、{self.nationality}人です。")

# 複数インスタンス作成
keiji = Person("ケイジ", "日本", 100)
jon = Person("ジョン", "アメリカ", 23)
nicolas = Person("二コラス","アメリカ",45)
kevin = Person("ケビン","日本",25)
```
```:呼び出し
keiji.hello("太郎")
jon.hello("花子")
nicolas.hello("佐藤")
```
```:出力
こんばんわ太郎さん、私はケイジ、日本人です。
こんばんわ花子さん、私はジョン、アメリカ人です。
こんばんわ佐藤さん、私は二コラス、アメリカ人です。
```




今回はここまで！

## 雑感
~~classムズイ！~~
classは使えるとおもろい！(。-`ω-)

## 最近AWSの認定試験SAPに合格したので、次はSCS(AWS Certified Security - Specialty)を受験する話。

はい。少し勉強した感じ、難しい。。年末に受験予定なので、合否問わず記事を投稿するのでお楽しみに！！