【Python3】プログラムを作成するために知っておきたいこと

# 概念
---
## ポイント

- 2 系と 3 系は別物

---
## パッケージ

### 「パッケージ」と「モジュール」の違い

- 「モジュール」は単一のファイル
- 「パッケージ」はディレクトリで `__init__.py` ファイルが格納されている。
- Python 3.3 以降 `__init__.py` ファイルのないディレクトリもネームスペースパッケージとして認識される。

---
### インポート

```python
## モジュールのファイル名(拡張子なし)、パッケージのディレクトリ名を指定する。
import modsample
```

```python
## パッケージやモジュールから一部の機能だけを参照
from modsample import MyClass
```

#### 「1 クラス 1 ファイル」にこだわらない。

- Visual Studio 等でクラスを追加すると `[クラス名].py` のファイルが作成されるが、ファイル名は名前空間として扱い(モジュール)、クラスを複数定義してかまわない。
- ファイル名とクラス名が同じだと `import` した際に冗長になる。

```python
import MyClass

# MyClass.py ファイルの MyClass クラスを呼び出す
if __name__ == '__main__':
    mc = MyClass.MyClass()
    mc.run()
```
- from モジュール import クラス の際に混乱する。

```python
from MyClass import MyClass

# MyClass.py ファイルの MyClass クラスを呼び出す
if __name__ == '__main__':
    mc = MyClass()
    mc.run()
```

---
## [クラス][]

```python
# 自作クラス
class MyClass(object):
    ## コンストラクタ
    def __init__(self, name='', *args, **kwargs):
        self.__name = name

    ## プロパティ
    @property
    def name(self):
        return self.__name

    @name.setter
    def name(self, value):
        self.__name = value
```

---
### コンストラクタ

厳密に言えばコンストラクタではありませんが、インスタンス生成後に呼ばれる `__init__()` メソッドを使います。
Python ではメソッドのオーバーロードができないため、`__init__()` メソッドも１つしか持てない。引数のデフォルト値を使って実現する。

---
### プライベート変数

オブジェクトの中からしかアクセス出来ないプライベート変数は、 Python にはありません。
アンダーバーを先頭に２文字つけることで疑似的にプライベート変数としてあつかいます。

###### [PEP8 日本語版][] > [メソッド名とインスタンス変数](https://pep8-ja.readthedocs.io/ja/latest/#id37) より引用
>Python はアンダースコアが先頭に二つ付いた名前にクラス名を追加します。つまり、クラス Foo に `__a` という名前の属性があった場合、この名前は `Foo.__a` ではアクセスできません (どうしてもアクセスしたいユーザーは `Foo._Foo__a` とすればアクセスできます)。

---
### プロパティ 

#### Get

`@property` の属性をつけて定義します。

#### Set

`@[プロパティ名].setter` の属性をつけて定義します。

---
### メソッド

#### 引数

| 種類 | 例 | 説明 |
| -------------- | ------------ | ---------------- |
| 位置引数       | `def func(value)` | 指定が必須な引数 |
| デフォルト引数 | `def func(value=None)` | 引数に値を設定しない際に、デフォルト値が使用されます。 |
| 可変長位置引数 | `def func(*args):` | 可変長の引数は配列として格納されます。 |
| 可変長キーワード引数 | `def func(**kwargs):` | 可変長の引数はキーワード配列として格納されます。 |

---
# 規約
[PEP8 日本語版][] に準拠する。

1. インデントは、スペースを4つ
2. 行の長さを、最大79文字まで
3. トップレベルの関数やクラスは、2行ずつ空けて定義する。
4. クラス内部では、1行ずつ空けてメソッドを定義する。

---
## 命名規則

---
### パッケージ名
全て小文字の短い名前。

```python
# パッケージ名の例
mypackage
```

---
### クラス名
パスカル形式

```python
# クラス名の例
MyClass
```

---
### 定数
大文字スネーク

```python
# 定数名の例
MY_CONSTS
```

---
### その他 (モジュール、関数、変数)
小文字スネーク

```python
# 関数名の例
my_function
```

---
### 引数

自由に命名することはできるが、以下のような規約に準拠する。

- インスタンスメソッドのはじめの引数の名前は常に `self` を使うのが一般的。
- クラスメソッドのはじめの引数の名前は常に `cls` を使うのが一般的。

---

## お作法
モジュール/パッケージとして import されたときに実行しないための条件判定。

```python
if __name__ == '__main__':
    # 処理
```
---
# 基本

---
## 四則演算子

| 演算子 | 記述例 | 意味 |
| :------: | :------: | ------ |
| + | 3 + 6 | 加算 |
| - | 5 - 2 | 減算 |
| * | 5 * 3 | 乗算 |
| / | 8 / 2 | 除算 |
| // | 8 // 2 | 除算 (小数点以下切捨て) |
| % | 5 % 3 | 剰余 |
| ** | 5 ** 2 | べき乗 |

---
## ビット演算子

| 演算子 | 記述例 | 意味 |
| :------: | :------: | ------ |
| & | 3 & 6 | AND |
| &#124; | 5 &#124; 2 | OR |
| ^ | 3 ^ 6 | XOR |
| ^ | 3 ^ 6 | XOR |
| ~ | ~a | ビット反転 |
| << | a << b | 左シフト |
| >> | a >> b | 右シフト |

---
## 比較演算子

| 演算子 | 記述例 | 意味 |
| :------: | :------: | ------ |
| == | a == b | b が a に等しい |
| != | a != b | b が a に等しくない |
| >  | a > b  | b より a が大きい |
| >= | a >= b | b より a が大きいか等しい |
| <  | a < b  | b より a が小さい |
| <= | a <= b | b より a が小さいか等しい |

---
# 参考サイト

- [Pythonドキュメント][]
- [PEP8 日本語版][]
- [Python にまつわるアイデア： Python のパッケージとモジュールの違い][]
- [Python におけるモジュールとパッケージは「名前空間」][]
- [Pythonのプロパティ宣言][]
- [常識ですよ？と言われないための引数入門][]
- [Python：常に__init__の代わりに__new__を使いますか？][]

[Pythonドキュメント]: <https://docs.python.org/ja/3/index.html>
[PEP8 日本語版]: <https://pep8-ja.readthedocs.io/ja/latest/>
[Python にまつわるアイデア： Python のパッケージとモジュールの違い]: <https://www.lifewithpython.com/2018/05/python-difference-between-package-and-module.html>
[Python におけるモジュールとパッケージは「名前空間」]:<https://qiita.com/sukobuto/items/15c1173b3f37f0306dd5>
[Pythonのプロパティ宣言]: <https://qiita.com/hiron2225/items/af48935d7bb066d33b3f>
[クラス]: <https://docs.python.org/ja/3/tutorial/classes.html>
[常識ですよ？と言われないための引数入門]: <http://note.crohaco.net/2014/python-argument-intro/>
[Python：常に__init__の代わりに__new__を使いますか？]: <https://codeday.me/jp/qa/20190110/131928.html>