Python講座 - 2024ver.

## 誰がこれを読むべきか
Pythonを学ぼうと思っている、プログラミング初心者
前提 : `$` の後に続くコマンドを実行する場合は、`$`を取り除いて入力してください

:::note info
初版年月日 : 2024年6月15日
更新年月日 : -
使用環境　 : macOS (Monterey~)
確認環境　 : Python3.8~
(Windowsでも動作に差はないと思いますが、シェルスクリプトの書き方が違うため、お気をつけください)
:::

## 目次
1. [はじめに](#はじめに)
    1. [プログラミングとは](#プログラミングとは)
    1. [プログラミング言語とは](#プログラミング言語とは)
    1. [Pythonとは](#pythonとは)
1. [セットアップ](#セットアップ)
    1. [python環境構築](#python環境構築)
    1. [pipとは](#pipとは)
    1. [python仮想環境とは](#python仮想環境とは)
        1. [venvとは](#venvとは)
        1. [pyenvとは](#pyenvとは)
        1. [condaとは](#condaとは)
    1. [エディター](#エディター)
1. [Pythonの書き方](#pythonの書き方 )
    1. [変数](#変数)
    1. [データ型](#データ型)
    1. [値の比較](#値の比較)
    1. [数値計算と文字列演算](#数値計算と文字列演算)
        1. [数値計算](#数値計算int型)
            1. [四則演算](#四則演算)
            1. [累算代入演算子](#累算代入演算子-四則演算)
            1. [ビット演算](#ビット演算)
        1. [文字列演算](#文字列演算str型)
    1. [関数の使い方](#関数の使い方)
        1. [自作関数の使い方](#自作関数の使い方)
        1. [外部関数の使い方](##外部関数の使い方一般例)
    1. [標準モジュールと、標準機能の使い方](#標準モジュールと標準機能の使い方)
        1. [print (shell表示)](#print-shell表示)
        1. [input (shell入力)](#input-shell入力)
        1. [if文 (条件分岐)](#if文-条件分岐)
        1. [for文](#for文)
        1. [While文](#while文)
        1. [time](#time-time)
        1. [os](#os-os)
        1. [subprocess](#subprocess)
        1. [datetime](#datetime)
1. [Pythonのお約束](#pythonのお約束)
    1. [PEPとは](#pepとは)
    1. [pepの中でも大事なルールたち](#pepの中でも大事なルールたち)
1. [番外編 pythonを事前コンパイル!?](#番外編---pythonを事前コンパイル)
## はじめに
### プログラミングとは
端的に言うと、機械を論理的に、かつ数学的に操作する方法のこと
機械は、(0,1)のみで表現された２進数の命令文(command)を実行している。
全ての機械上での動作は、(0,1)の形に変換されているが、これを人間が書くのは、あまりにも非効率で、ミスが多発するうえ、人間が書き込める領域を定義するためにもプログラミング言語のようなもの(shellscript)を使っているため、直接的に(0,1)で機械と会話することは不可能である。
人間がわかりやすいように、機械語に翻訳するための必要最低限の制約が設けられている言語を正しく書くことが、プログラミングである。

### プログラミング言語とは
全てのプログラミング言語は、実行時 or 事前にコンパイル（機械語に翻訳）する
機械語とは、人間に読むことのできない状態の文字列で、(0,1)のみで構成されている

ここで、事前に明示的に機械語に翻訳する必要がある言語をコンパイラ言語と呼び、それ以外をスクリプト言語と呼ぶ
スクリプト言語は、基本的にインタプリタ言語でもある(定義は人により、明確ではない)

![アセット 1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3793916/18d4e403-aa14-2c84-0ff7-790b3f3b547d.png)

### Pythonとは
元々は、計算のために作成されたプログラミング言語である

|年月|内容|備考|
|---|---|---|
|1991年2月|ヴァンロッサムがPython 0.90のソースコードを公開||
|1994年1月|Python 1.0 を公開 (ラムダ計算, map関数, reduce関数の実装)||
|2000年10月|Python 2.0 を公開 (Unicode, List, garbage collectionを実装)|一躍有名に|
|｜|||
|2008年10月|Python 2.6 を公開 (python2->3以降試験中のリリースとなる)||
|2008年12月|Python 3.0 を公開 (西暦3000年にリリースすることを当初目標としていたため、Python3000とも呼ばれていた)|
|2010年7月|Python 2.7 を公開 (Python2の最後のリリースとなった)||
|｜|||
|2023年10月|Python 3.12を公開 (最新版)|現在ユーザー数760万人以上(LinkedIn調べ)|

https://ja.wikipedia.org/wiki/Python 

を参考にした

<details><summary>python-version年表</summary>

|ver|年|
|---|---|
|0.90|1991|
|1.0|1994/1|
|1.1|-|
|1.2|-|
|1.3|-|
|1.4|-|
|1.5|-|
|1.6|-|
|↓||
|2.0|2000/10/16|
|2.1|2001/4/15|
|2.2|2001/12/21|
|2.3|2003/7/29|
|2.4|2004/11/30|
|2.5|2006/9/19|
|2.6|2008/10/1|
|↓||
|3.0|2008/12/3|
|(2.7)|(2010/7/4)|
|3.1|2009/6/27|
|3.2|2011/2/20|
|3.3|2012/9/29|
|3.4|2014/3/16|
|3.5|2015/9/13|
|3.6|2016/12/23|
|3.7|2018/6/27|
|3.8|2019/10/14|
|3.9|2020/10/5|
|3.10|2021/10/4|
|3.11|2022/10/24|
|3.12|2023/10/2|
</details>


今もっともユーザー数が多いプログラミング言語は、Javascript(webサイトの動きなどをつける言語)となっているが、PCのシステム操作などの部類に入るプログラミング言語の中でもっともユーザー数が多い言語が、Pythonである。
Pythonとは、先ほど述べたインタプリタ言語に属している。つまり、実行中に機械語に翻訳していく言語だ。
私個人の感想になるが、C++やJavaなどのコンパイル言語と違って、コンパイルエラーの存在をほぼ気にしなくていいため、エラーが出た時の原因解明がしやすく、修正がしやすい。そして何より、人間にとって可読性の高い言語である、という点でPythonを気に入っている。(私は、HTML, CSS, Javascript, Kotlin, PHPの勉強をしている)

Pythonの強みは、前述の通り、人間にとって可読性が極めて高いことだ。
弱みとしては、繰り返し同じ処理を行うときに、処理速度でコンパイラ言語に負けてしまうという点が挙げられるだろう。（事前にコンパイルするためのパッケージも作られている)

## セットアップ
### Python環境構築
1. [Python - Download](https://www.python.org/downloads/) からPythonのバージョンを選択してダウンロードする
1. condaでセットアップする (これについては[condatとは](#condaとは)を参照ください)
1. brewで入れる 
    ```sh
    brew install python@3 
    # versionを指定する場合は、brew install python@3.xx のように指定してください
    ```
:::note info
Pythonが入っているか確認するには、以下の通りに確認します
```shell
$ python3 --version
Python 3.xx.y
# もし、"zsh: command not found: python3" と表示されたら、
# 上記の方法のどれかでセットアップし、実行後に再び上のコマンドにて確認してください
```
:::



### pipとは
pythonで使うことのできるパッケージ(numpy, matplotlib など)をインストールするツールです
```shell
$ pip --version
pip xx.x from XXX/YYY/ZZZ/pip (python 3.xx) #x,y,zなどのところは、それぞれの環境によって違います
# もし、pip --verisonで、"zsh: command not found: pip"となった場合は、下のコマンドを実行してください
$ python3 -m pip install pip
```
また、pipの使い方は、以下の通りです(xxxxのところは、パッケージ名が入ります)
```shell
$ pip install xxxx
# version(y.y.y)を指定したい場合は、
$ pip install xxxx==y.y.y
# requirements.txtを出力する方法
$ pip freeze > requirements.txt
# requirements.txtを使ってインストールする方法
$ pip install -r requirements.txt
```
<details><summary>入れておくことをお勧めするパッケージリスト</summary>

- numpy 
- matplotlib
- pip-review
- tqdm
- joblib
- jupyterlab
- jupyter
- pandas
- scipy
- xlrd
- XlsxWriter
- Pillow
- opencv-python
- plotly
- requests
- Flask
- Django
- PyInstaller


</details>

### Python仮想環境とは
名前の通り、Pythonを実行する環境を、仮想環境に指定するものである
これによってパッケージの依存関係の整理などを容易にすることができる
<details><summary>メリットについて詳しく</summary>

- 複数のバージョンのPythonを使用できる
- 仮想環境を使うメリットに同じモジュール内でバージョンの使い分けが可能
- 依存関係エラーが出たら、その環境を即座に削除すればいい
  (直すこともできますが、絡まって面倒なことになると、削除した方が楽なことが多い)

</details>

#### venvとは
venvを使う場合、基本的にpythonのバージョンは、システム上に一つしか置けない
pythonに標準で載っている仮想環境システム
プロジェクトごとに、以下のコマンドにてvenv環境をビルドする
```shell
# "pass/to/directory"に、絶対パス or 相対パスでフォルダーを指定してください
python3 -m venv "pass/to/directory"
source "pass/to/directory/venv/bin/activate"
```
#### pyenvとは
これは、pythonのバージョンを複数扱うことを得意とするツール
以下の方法でインストール可能
```shell
pip install pyenv
```
使い方は、解説を省略する。以下などのサイトを参照してもらいたい

https://envader.plus/course/8/scenario/1076

#### condaとは
pythonの強みである、計算系に強い独自のパッケージなどを多く兼ね備えた仮想環境構築ツールである
pythonを日々使うなら、絶対に入れといて損ないが、あまり使わない場合は非推奨かもしれない(容量を圧迫する)
操作方法は、ここでは省略するが、詳細は以下のサイトなどを参照してもらいたい

https://qiita.com/yasushi-jp/items/7ce0975db7a7e9ac7991

<details><summary>condaのダウンロード方法(省略版)</summary>

```python
macos_arm64(Apple Silicon) = "https://repo.anaconda.com/archive/Anaconda3-2024.02-1-MacOSX-arm64.sh"
macos_x86(Intel Chip) = "https://repo.anaconda.com/archive/Anaconda3-2024.02-1-MacOSX-x86_64.sh"
```
上のリンクの中から、適した環境のものを選んで、コピーして、"LINK"のところを置き換えてください
```shell
curl -s "LINK" | sh
```
これを実行したのち、指示に従って実行すれば、Condaのダウンロードは完了です
</details>

### エディター
1. Visual Studio Code
1. Pycharm
1. Atom
1. Jupyter Notebook

学生のうちは、JetBrainsのPycharmをおすすめします(年間10000円ほどのプランが、学生だと無料になります)
[JetBrains - 学生ライセンス申し込みページ](https://www.jetbrains.com/shop/eform/students)

## Pythonの書き方
パッケージやライブラリについてわからないことがあるときは、Qiitaなどで調べるか、[Python公式 -docs-](https://docs.python.org/ja/3/library/)などを見るなど、自分で調べるようにしましょう
### 変数
変数とは、数学で使うような、xやyのこと(a,bなどはパラメーターのことが多い)
`変数名 = 内容` の形で定義する
使用できる文字は a ～ z 、 A ～ Z 、 0 ～ 9 、アンダーバー(_)、漢字など
- 1文字目に数値は使用できない
- 1文字目にアンダーバーは使用できるが、推奨しない(他の用途でも使うため)
- 大文字と小文字は区別される
- [予約語](https://note.nkmk.me/python-keyword-reserved-word/) は使用できない
```python
a = 1234567890
b = "QWERTYUIOP __ひらがな漢字"
漢字 = "漢字"
# このように、変数名に日本語などを使用することは可能だが、非推奨(後々使いにくくなる)
# 基本的に変数名は英語(アルファベット)にしたほうがいい
```
また、変数は、特別な書き方をしない限り、再代入が可能である(変数の定義の仕方自体に変数ロックの仕組みを搭載している言語が多いのだが、pythonでは少し面倒な方法を取らない限り制限することはできない)
<details><summary>再代入を防ぐ方法</summary>
少々汚いコードかと思いますが、お許しください

1. クラスを使う方法

    ```python
    class Immutable:
        def __init__(self, value):
            self._value = value
            self._is_set = False
        @property
        def value(self):
            return self._value
        @value.setter
        def value(self, new_value):
            if self._is_set:
                raise ValueError("再代入はできません")
            self._value = new_value
            self._is_set = True
    # 使用例
    try:
        var = Immutable(10)
        print(var.value)
        var.value = 20  # 最初の代入は成功
        print(var.value)
        var.value = 30  # 再代入しようとするとエラー
    except ValueError as e:
        print(e)
    ```
    
2. デコレータを使う方法
    ```python
    def immutable(cls):
    class Wrapper(cls):
        def __setattr__(self, key, value):
            if key in self.__dict__:
                raise AttributeError(f"'{key}'の再代入はできません")
            super().__setattr__(key, value)
    return Wrapper

    @immutable
    class MyClass:
        def __init__(self, value):
            self.value = value

    # 使用例
    try:
        obj = MyClass(10)
        print(obj.value)
        obj.value = 20  # 再代入しようとするとエラー
    except AttributeError as e:
        print(e)
    ```

</details>

変数スコープの詳しい仕組みなどは、以下などを確認ください

https://qiita.com/msssgur/items/12992fc816e6adf32cff

### データ型
データ型は、基本的に自動で推測され、定義されますが、手動で明示的に定義しなくてはいけない

|型名|名称|説明|記述例|明示的型定義例|
|--|--|--|--|--|
|str|文字列|"か、'で括って定義する|str = "abc"|`str("abc")`|
|int|整数|小数点を含まない整数|int = 100|`int(100)`|
|float|浮動小数点|小数点を含む数値|float = 3.14|`float(3.14)`|
|bool|ブール|True or False|3.1==3.14 : False <br>3.11==3.11 : True|`bool(True)`|
|datetime|日付|日付|today = <br>datetime.datetime.now().strftime("%Y/%m/%d")|-|
|list|配列|`,`で区切る 各要素の直接入れ替えが可能|list = ["list", 1, 2]|`list[str, int, int]=["list", 1, 2]`|
|tuple|タプル|`,`で区切る 各要素の入れ替えが不可能|tuple = ("tuple", 1, 2)|`tuple[str, int, int]=("tuple", 1, 2)`|
|dict|辞書|`{}`で定義する 要素間に`:`を挟む <br>キー値と合わせて値を設定することにより、キー値を元に値を参照できる。|dict = {"word1":10, "Key2":20, "Key3":30}|`dict[str,int]={"word1":10, "Key2":20, "Key3":30}`|

### 値の比較

|記号|意味|数式表記|
|---|---|---|
|a==b|等しい|$a=b$, 同意義で、a is b|
|a!=b|aとbが異なる|$a\neq	b$, 同意義で、a is not b|
|a<b|aがbより小さい|$a<b$|
|a>b|aがbより大きい|$a>b$|
|a<=b|aがb以下|$a\leqq b$|
|a>=b|aがb以上|$a\geqq b$|
|a in b|aがbに含まれる|$a\in b$|
|a not in b|aがbに含まれていない|$a\notin b$|

### 数値計算と文字列演算
#### 数値計算(`int型`)
##### 四則演算

|算数表記|Python表記|
|--|--|
|a+b|a+b|
|a-b|a-b|
|a×b|a*b|
|a÷b|a/b|
|$a^b$|a**b|
|a÷bの商<br>(切り捨て除算)|a//b|
|a÷bの余り|a%b|

##### 累算代入演算子 (四則演算)
a ?=b の形で表記し、aの場所には、変数名、bには、変数or数式が入ることが一般的
aに対して、bと?による演算を行い、aの変数に再び格納する

|Python表記|意味|
|---|---|
|a+=b|a=a+b とする|
|a-=b|a=a-b とする|
|a*=b|a=a*b とする|
|a/=b|a=a/b とする|
|a%=b|a=a%b とする|
|a**=b|a=a**b とする|
|a//=b|a=a//b とする|
|a&=b|a=a&b とする|
|a\|=b|a=a\|b とする|
|a^=b|a=a^b とする|
|a<<=b|a=a<<b とする|
|a>>=b|a=a>>b とする|

##### ビット演算
ここは、知らなくても構わないですが、知っておくことで何かに活かせるかもしれません。
読みたい方は、折りたたみを展開して読んでください。
<details><summary>二進数法とは
</summary>
前述の通り、PCでは、(0,1)のどちらかのみで全てを表現しています
これを直接的に操作することは通常、行わないですが、たまに使うことがあります
そんな時のために、(0,1)を直接的に操作するための便利ツール (ビット演算子) が存在します

超ざっくりとしか扱いません。
詳しく知りたい場合は、ご自分でお調べください

0 : OFF
1 : ON と考えることができます

0 or 1 の１文字分を`1bit`と表記し、これを8桁集めたものを、`1B`(byte)で表記します
今回は、1B演算を例に扱います

|$2^7$|$2^6$|$2^5$|$2^4$|$2^3$|$2^2$|$2^1$|$2^0$|10進数|
|---|---|--|--|--|--|--|--|---|
|1|1|1|1|1|1|1|1|255|
|1|1|0|1|1|1|0|1|221|
|1|0|0|0|0|0|1|0|130|

</details>
<details><summary>ビット演算の書き方</summary>

##### ビット演算 & 累算代入演算子
```python
# 0bとは、2進数であるということを定義するための文字列です
# この項の中では、a,bを以下の通り定義します
a = 0b11010110 #10進数表記 : 214
b = 0b00111011 #10進数表記 : 59
```
1. AND演算 `&`
2つスイッチを比較して、どちらも1なら1、どちらか片方でも0の場合は0を返す
`c = a&b`
a = 11010110
b = 00111011
↓　　 ↓
c = 00010010
    ```python
    a = 0b11010110
    b = 0b00111011
    print(a&b)
    print(bin(a&b))
    # 以下出力
    # 18 
    # 0b10010
    ```
1. OR演算 `|`
2つスイッチを比較して、どちらかが1なら1、どちらも0の場合は0を返す
a = 11010110
b = 00111011
↓　　 ↓
c = 11111111
    ```python
    a = 0b11010110
    b = 0b00111011
    print(a|b)
    print(bin(a|b))
    # 以下出力
    # 255
    # 0b11111111
    ```
1. NOT演算 `~`
スイッチのON/OFFの状態をすべて逆転させ、0は1に、1は0に変える
(符号なし2進数で定義しているため、不自然だが、`-0b11010111`表記で出力される)
a = 11010110
↓　　 ↓
a'= 00101001
    ```python
    a = 0b11010110
    print(~a)
    print(bin(~a))
    # 以下出力
    # -215
    # -0b11010111
    ```

1. XOR演算 `^`
2つスイッチを比較して、どちか片方だけ1なら1、どちらも0またはどちらも1の場合は0を返す。(差を調べる)
a = 11010110
b = 00111011
↓　　 ↓
c = 11101101
    ```python
    a = 0b11010110
    b = 0b00111011
    print(a^b)
    print(bin(a^b))
    # 以下出力
    # 237
    # 0b11101101
    ```
1. 左ビットシフト演算 "<<"
`a << n`の形で、aのON/OFFの状態を、左にn個ずらす
(つまり、右からn桁分0で埋める)
ずらした事により空いた枠には0が入る。
a = 11010110
n = 2
↓　　 ↓
c = 1101011000
    ```python
    a = 0b11010110
    n = 2
    print(a<<n)
    print(bin(a<<n))
    # 以下出力
    # 856
    # 0b1101011000
    ```

1. 右ビットシフト演算 ">>"
`a >> n`の形で、aのON/OFFの状態を、右にn個ずらす
(つまり、右からn桁分を削除する)
ずらした事により空いた枠には0が入る。
a = 11010110
n = 2
↓　　 ↓
c = 110101
    ```python
    a = 0b11010110
    n = 2
    print(a>>n)
    print(bin(a>>n))
    # 以下出力
    # 53
    # 0b110101
    ```

累算代入演算子は、四則演算の際と同じように、ビット演算子を`?=`の?のところに当てはめるだけ
</details>

#### 文字列演算(`str型`)
文字列は、`"xxx"` `'xxx'`か、のように、クオーテーションかダブルクオーテーションでくくる
数字を文字列として扱いたいときも、`"123"`のようにして扱うことができる

文字列 + 文字列 : OK
文字列 + 数値　 : OK (型変換をすれば)
文字列 * 数値　 : OK (文字列を、"数値"回分繰り返す)
文字列 - 数値　 : NG
文字列 - 文字列 : NG

:::note info
Pythonでは、何かに番号付け(index)をするとき、0から番号をつけ、0,1,2,3...とします
:::

```python
print("Hello"+" World")
# Hello Wolrd
a = "Hello "
b = "World."
c = "Hello World."
print(a+b)
# Hello World.
print(a-b)
''' 出力(Error)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for -: 'str' and 'str'
'''
print(a*3)
# Hello Hello Hello 
print(c[0:5])
# Hello (c変数に格納されている文字列の、indexが0から5までの文字を抽出する)(また、この場合の":"は、a:bで、aからbまで、の範囲を意味する)
print(c[1])
# e (前述の通り、Pythonでは、indexの開始番号が0のため、[1]で指示されるのは、2文字目である)
print(c.replace)
```
なお、数値の場合は使用可能だった、累算代入演算子は、文字列の時は使用が推奨されない
[PEPの中でも大事なルールたち](#pepの中でも大事なルールたち) の項目5番目に書いてあるため、そちらを見ていただきたい
### 関数の使い方
#### 自作関数の使い方
define(定義する)が由来となって、関数だよ、と宣言する文言に、`def`を用いる
下のようなの書き方をする
```python
def function_name(input_value):
    return "処理をここに書く"

# 例 (nameは、入力値を受け取って、変数`name`として格納する)
def hello(name):
    return "Hello : "+name
# 例 (使い方)
name = input("Please write your name : ")
print(hello(name))
```
ただし、関数名は、ASCII互換性のある文字列によって、全てを小文字の英文字で、区切るときは`_`で区切ることを推奨します
[PEPの中でも大事なルールたち](#pepの中でも大事なルールたち) の4番目の項目にも書いてあります

#### 外部関数の使い方(一般例)
pip / condaでインストールしたパッケージを使用する方法を解説する
今回は、numpyとmatplotlibを例にとる
`pip install numpy`でダウンロードする (`conda install numpy`でも可)
`pip install matplotlib`でダウンロードする(`conda install matplotlib`でも可)
`import packagename`で導入し、`packagename.modulename(value)`の形で使用する

:::note info
パッケージによって使い方は違うため、その都度調べて徐々に覚えていくことをお勧めします
:::


```python
#import numpyだけだと、関数名はnumpyとして読み込まれるが、長くて面倒なため、npとして読み込む
import numpy as np # import x as y で、xをyとして読み込む、の意
import matplotlib.pyplot as plt #matplotlibというパッケージの中のpyplotモジュールを、"plt"として読み込んでいる
a = np.linspace(-10, 10, 41) # -10から10の間を41個に区切る (0.5刻み)
print("Output\n"+a) # 動作確認のための出力
# Output : 
# [-10.   -9.5  -9.   -8.5  -8.   -7.5  -7.   -6.5  -6.   -5.5  -5.   -4.5
# -4.   -3.5  -3.   -2.5  -2.   -1.5  -1.   -0.5   0.    0.5   1.    1.5
#  2.    2.5   3.    3.5   4.    4.5   5.    5.5   6.    6.5   7.    7.5
#  8.    8.5   9.    9.5  10. ]

def sigmoid(a):
    # 関数の定義(この場合は、1/1+exp(-x)という数式に入力を当てはめているため、このaは、int型か、float型かndarry型であるべき)
    # 今回は、このaには、ndarry型の入力(ベクトルが入る)
    return 1/(1+np.exp(-a))

print(sigmoid(a)) # 動作確認のための出力

# 以下グラフの定義
plt.plot(a, sigmoid(a))
plt.xlabel('a')
plt.ylabel('sigmoid(a)')
plt.title('Sigmoid Function')
plt.grid(True)
plt.show()
```
以下のような出力が得られると思います
![Sigmoid.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3793916/8312dd71-d284-35e0-5b0e-c36b8976aa90.png)



これらのPythonパッケージの使い方などは、エディターによっては説明がエディター内で読める場合があります

[PyCharm](https://www.jetbrains.com/ja-jp/pycharm/)の例 : 
![スクリーンショット 2024-06-17 9.29.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3793916/d909bde9-0de4-55e1-010b-201ca5570f47.png)

https://www.jetbrains.com/ja-jp/pycharm/features/coding_assistance.html

### 標準モジュールと、標準機能の使い方
#### print (shell表示)
`print("message")`の形で書く
shellに出力する
`print()`の括弧の中に入るものは、データ(直書きでも構わないし、変数でも構わないし、数式を直接入れても構わない)
#### input (shell入力)
`a = input()`の形でaにユーザーからのshell入力を受け取って代入させる
`a = input("Please write comment : "); print(a)`のようにすることで、以下のようにできる
![スクリーンショット 2024-06-17 13.10.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3793916/0e75e872-65dd-eb3e-b041-b09cf521f081.png)
![スクリーンショット 2024-06-17 13.12.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3793916/3d44a132-28b1-eac6-6a13-5448869d4943.png)

```shell
$ python3 a.py
Please write comment : 23 
<class 'str'>
```

なお、input("")で受け取ったデータは、基本的に上記の通りstr型で収納されてしまうため、数値として扱いたい場合は`int(input())`のように書くなど、明示的型定義が必要となる

#### if文 (条件分岐)
[値の比較](#値の比較)の項目を確認してからご覧ください

```python
if a ? b:
    "write process here"
if a ? b:
    "write process here"
else:
    "write process here"
```
この書き方がベースとなる(?のところに、条件比較が入る)
以下に、a(int)とb(int)を、$a=b$, $a>b$, $a<b$ の場合に分けて出力する方法を書く

1. 書き方①

    ```python
    if a==b:
        print("a=b")
    if a>b:
        print("a>b")
    if a<b:
        print("a<b")
    ```

1. 書き方②

    ```python
    if a==b:
        print("a=b")
    else: # つまりは、"if a!=b:"と等しい
        if a>b:
            print("a>b")
        if a<b
            print("a<b")
    ```
方法1と2どちらが使いやすいだろうか
この程度のシンプルな問題ならば、間違いなく 1 の方だろう
しかし、機械処理などをビジュアルライクに書きたい場合 (引き継ぎが存在するプロジェクトや、とにかくコードが長くなって自分でもわからなくなるとき)は、 2 の方を採用することもあるので、柔軟に対応できるようになった方がいい

また、else ifの形を多用する人向けの書き方として、`elif`というものがある
使い方は、以下の通りで、圧倒的に短くかける
```python
if a==b:
    print("a==b")
elif a>b:
    print("a>b")
elif a<b:
    print("a<b")
```

また、これはif文に限ったことではないのだが、以下のような論理式と呼ばれる書き方がある
- and
- or
- but

例として、以下のような書き方ができる
```encouragement.py
test_score = int(input("average Score : "))
lower_test_score = int(input("Lower Test Score : "))
# test_score=100, test_score≧90, 80≦test_score<90 / 60≦test_score<80, 40≦test_score<60, test_score<40 の場合に分けて考える
if test_score==100:
    print("Perfect!!")
if test_score>=90:
    print("You did a Great job!")
if test_score>=80 and test_score<90:
    print("Good job!")
if (test_score>=60 and test_score<80) or (lower_test_score>40 and lower_test_score<=60):
    print("Let's think about what went wrong")
if (test_score>=40 and test_score<60) or (lower_test_score>20 and lower_test_score<=40):
    print("What happened?")
else:
    print("Let's study positively...")
```
なお、論理式は、優先度が決まっており、それに則さない書き方をする場合は、例のように、`()`でくくる必要がある
$not > and > or $ の順番である
#### for文
`for i in x`の形で、iがxを尽くすまで繰り返す、の意味を持つ
なお、`for i`のiは、任意の変数名で構わない 
つまり、回数指定をしたいときなどにも`for文`を良く使う
`for i in range(x)`の形もよく使うが、これには`range`の独自の機能が関わっている
詳しく知りたい場合は、以下のサイトなどをご参照ください

https://www.javadrive.jp/python/function/index6.html

```python
for i in [1, 2, 3, 4, 5]:
    print(str(i)+" Hello")
# 1 Hello
# 2 Hello
# 3 Hello
# 4 Hello
# 5 Hello

# 同じ意味で、

for i in range(4):
    print(str(i)+" Hello")
# 0 Hello
# 1 Hello
# 2 Hello
# 3 Hello
# 4 Hello
```
また、以下のような例でも使える(長いため、折り込み式にしてある)

<details><summary>例</summary>

```python
message = 'Hello Python'
print(message[0])
print(message[1])
print(message[2])
print(message[3])
print(message[4])
print(message[5])
print(message[6])
print(message[7])
print(message[8])
print(message[9])
print(message[10])
print(message[11])
"""
H
e
l
l
o
 
P
y
t
h
o
n

という出力が得られる
"""
```
以下のコードは、同じ働きをする
```python
message = 'Hello Python'
for i in message:
    print(i)
```
</details>

#### While文
`while x`の形で、x のところには条件を書き、その条件下のみでそれ以降のコードは実行される、という意味を持つ
for文とにているように聞こえるが、本質的にはだいぶ違う
`for i in x`文では、iがxを尽くすまで、**回数を指定して**繰り返していたが、
`while x`文では、iがxではなくなるまで**回数を直接的に指示せずに**繰り返させる
使い方としては、以下が挙げられる
`while True`は、`break`によって終了を宣言しない限り、無限に処理を続ける
そのため、if文と合わせてbreakを宣言する必要がある

```python
a = 0
while a<=20:
    a+=1
print(str(a)+" Process was end.")
# 21 Process was end.
```
```python
a = 0
while True:
    a+=1
    if a>20:
        break
print(str(a)+" Process was end.")
# 21 Process was end.
```
また、上のコードは、以下のようにも書ける
```python
a = 0
while (a<=20) == True:
    a+=1
print(str(a)+" Process was end.")
# 21 Process was end.
```

#### time (time)
以下をご参照ください

https://docs.python.org/ja/3/library/time.html

#### os (os)
以下をご覧ください

https://docs.python.org/ja/3/library/os.html

なお、`pip install numpy`というコードを実行したい場合は、
`os.system("pip install numpy")`と、`subprocess.run(["pip", "install", "numpy"])`の2通りが考えられるが、後者の方を使用した方がいい場合が多い

#### subprocess
以下をご覧ください

https://docs.python.org/ja/3/library/subprocess.html

#### datetime
以下をご覧ください

https://docs.python.org/ja/3/library/datetime.html

## Pythonのお約束
### PEPとは
Python Enhancement Proposalの略
Pythonの開発者コミュニティがPythonの言語仕様や機能の改善、追加、変更に関する提案を行うための文書のこと。
* PEP8 in English : https://peps.python.org/pep-0008/ 
* PEP8 in Japanese : https://pep8-ja.readthedocs.io/ja/latest/ 
にて読むことができる

> PEP stands for Python Enhancement Proposal. A PEP is a design document providing information to the Python community, or describing a new feature for Python or its processes or environment. The PEP should provide a concise technical specification of the feature and a rationale for the feature.
>
>We intend PEPs to be the primary mechanisms for proposing major new features, for collecting community input on an issue, and for documenting the design decisions that have gone into Python. The PEP author is responsible for building consensus within the community and documenting dissenting opinions.
>
>Because the PEPs are maintained as text files in a versioned repository, their revision history is the historical record of the feature proposal. This historical record is available by the normal git commands for retrieving older revisions, and can also be browsed on GitHub.
>
> from [PEP1](https://peps.python.org/pep-0001/#id31)

このPEPのルールに則ってコードを書くことは、コードが正しく実行されることの次に大事なことである。ただし、PEPに則ることによって、動作が不安定になったりすることはあってはならない
> *A Foolish Consistency is the Hobgoblin of Little Minds*
> *一貫性にこだわりすぎるのは、狭い心の現れである*
>
> *from [PEP8](https://peps.python.org/pep-0008/)*


### PEPの中でも大事なルールたち
私の主観で選んだルールたち5選です。
詳細は、[PEP8](https://pep8-ja.readthedocs.io/ja/latest/)をみてください

1. インデントは、"Space"*2 or "Tab"で、ファイル内あるいはプロジェクト内で統一する
    <details><summary>例</summary>

    ```python
    # 悪い例 "Tab"と"Space"*2のインデントが混在
    message = "Hello "
    a = input("Please write your name : ")
    if type(a) = int :
        print(message + a)
    else:
      print()
    ```
    ```python
    # 良い例 この場合は"Tab"でインデント
    message = "Hello "
    a = input("Please write your name : ")
    if type(a) = str :
        print(message + a)
    else:
        print("Error.")
    ```

    </details>

1. コード内の文字は、一列あたり79文字に収める(無理な場合は、99文字に収める)
    <details><summary>例</summary>

    ```python
    # 悪い例 ("command = "の行が132文字ある)
    if "plant" in conda_plant:
        conda_prefix = subprocess.check_output(['conda', 'info', '--base']).decode('utf-8').strip()
        activate_script = os.path.join(conda_prefix, 'etc', 'profile.d', 'conda.sh')
        command = f"source {activate_script} && conda activate plant && conda install -n plant --file conda_env.txt && conda update --all"
        os.system(f"bash -c '{command}'")
        break
    ```

    ```python
    # 良い例 ("command = "の行で、f"~~~"改行して、f"~~~"と書いた)
    if "plant" in conda_plant:
        conda_prefix = subprocess.check_output(['conda', 'info', '--base']).decode('utf-8').strip()
            activate_script = os.path.join(conda_prefix, 'etc', 'profile.d', 'conda.sh')
            command = (f"source {activate_script} && conda activate plant && conda install -n plant --file "
                       f"conda_env.txt && conda update --all")
            os.system(f"bash -c '{command}'")
    ```
    
    </details>


1. import文の書き方(通常、パッケージ一つに対して一行)
    <details><summary>例</summary>
    
    ```python
    # 悪い例
    import os, sys, numpy, matplotlib
    ```
    ```python
    # 良い例
    import os
    import sys
    import numpy
    import matplotlib
    ```
    ```python
    # 例外
    from subprocess import Popen, PIPE
    # fromを使う時は、面倒なため、","の使用が許されている
    ```
    </details>
1. 命名規則
    * 単一の文字 'l' (小文字のエル)、'O' (大文字のオー)、'I'(大文字のアイ) を決して変数に使わない
    * ASCII互換性を持たせる
    * クラス名は、<details><summary>CapWords方式</summary>最初の1文字を大文字を指定し、次の文字からはキャメルケース（アルファベットで複合の単語を組み合わせる）を用いる方式のこと
    例 : "MyFirstClass" </details> を使う
    * 定数名は、全てを大文字で書く
1. 〈**推奨**〉変数の文字列演算での直接置き換えはやめよう
    <details open><summary>つまり...</summary>
    
    ```python
    # 悪い例
    a = "Hello "
    b = "World"
    a+=b # a = a+b
    print(a)
    ```
    ```python
    # 良い例
    a = "Hello "
    b = "World"
    c = a+b
    print(c)
    ```
    なお、この程度の単純なコードであれば、上の"#悪い例"の書き方でも構わないし、下の書き方でもいい
    ```python
    a = "Hello "
    b = "World"
    print(a+b)
    ```
</details>

## 番外編 - Pythonを事前コンパイル?!
pythonを書いて、インタプリタ言語として実行する場合は、`.py`ファイルで保存するが、事前にコンパイルした場合は、`__pycache__`フォルダーの元に、`.pyc`として保存される
```shell
$ python3 -m compileall xxx.py
```
の形で実行し、これまで通り`python3 xxx.py`で実行することで、実行前の呼び出し時間が短くなる (実行時間は大して変わらない)