【Pythonチュートリアル】Pythonの気楽な入門編

# はじめに
Pythonチュートリアル第3版を読み進めて、勉強した内容をメモしていこうという試みです

[Pythonチュートリアル 第3版](https://www.oreilly.co.jp/books/9784873117539/)

そして読み終えた暁にはこの試験を受けたいと思います
終わるころには試験も開始している・・・、はず！

[Python 3 エンジニア認定基礎試験](https://www.pythonic-exam.com/exam:embed)

続くといいな、続けばいいな

# Pythonを電卓として使う
## 数値
### 数値の型
- 整数は`int`型を持つ
- 小数を伴う数は`float`（浮動小数点）型を持つ
- 除算は常に`float`型を返す

```python
>>> 2 + 2
4
>>> 50 - 5 * 6
20
>>> (50 - 5 * 6) / 4
5.0
>>> 8 / 5
1.6
>>> 17 / 3
5.66666666666667
```

### 四則演算
- 切り下げ除算をおこなって整数解を得たい場合は（剰余を捨てたい場合は）`//`演算子を使う
- 剰余のみを得たい場合は`%`演算子を使う

```python
>>> 17 // 3
5
>>> 17 % 5
2
>>> 5 * 3 + 2
17
```

- `**`演算子を使うことで累乗を求めることができる

```python
>>> 5 ** 2
25
>>> 2 ** 7
128
```

- 演算対象の型が混合していた場合、整数は浮動小数点数に変換される
 
```python
>>> 3 * 3.75 / 1.5
7.5
>>> 7.0 / 2
3.5
```

### 変数
- 等号（`=`）は変数に値を代入するのに使う

```python
>>> width = 20
>>> height = 5 * 9
>>> width * height
900
```

- 変数は「定義」（値を代入）しないで使おうとするとエラーが出る

```python
# 未定義の変数にアクセスを試みると変数定義されていないためNameErrorが出る
>>> n
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'n' is not defined
```

- 対話モードでは、最後に表示した値を変数「`_`」（アンダースコア）に代入してある

```python
>>> tax = 12.5 / 100
>>> price = 100.50
>>> price * tax
12.5625
>>> price + _
113.0625
>>> round(_, 2)
113.06
```

### その他の数値型
- 十進数（Decimal）や有理数（Fraction）など、さまざまな数値型がサポートされている
- 複素数もサポートされており、その虚部を示すのに接尾辞「j」または「J」を使う（`3+5j`などとする）

## 文字列
### 引用符
- 引用符にはシングルクォート（'...'）もダブルクォート（"..."）も使えてどちらも同じ結果になる
  - シングルクォートの中ではダブルクォートをエスケープする必要がない<br>（シングルクォートは`\'`のようにエスケープする必要がある）
  - ダブルクォートの中ではシングルクォートをエスケープする必要がない
- バックスラッシュ（`\`）でクォート文字のエスケープができる
- バックスラッシュは、日本語キーボードおよび日本語フォントでは円記号を入力および表示される

```python
>>> 'spam eggs' # シングルクォート
'spam eggs'
>>> 'doesn\'t' # シングルクォートは\ でエスケープするか...
"doesn't"
>>> "doesn't" # ... ダブルクォートを使う
"doesn't"
>>> '"Yes," he said.'
'"Yes," he said.'
>>> "\"Yes,\" he said."
'"Yes," he said.'
>>> '"Isn\'t," she said.'
'"Isn\'t," she said.'
```

- インタープリタでは、文字列は引用符に囲まれ、特殊文字は`\`でエスケープされた状態で出力される
- 表示の引用符がダブルクォートとなるのは、文字列自体がシングルクォートを含みダブルクォートを含まない場合のみで、それ以外はシングルクォートとなる

```python
>>> '"Isn\'t," she said.'
'"Isn\'t," she said.'
>>> print('"Isn\'t," she said.')
"Isn't," she said.
>>> s = 'First line.\nSecond line.'
>>> s # print() しないで表示すると\n が出力に含まれる
'First line.\nSecond line.'
>>> print(s) # print() を使うと\n で改行が生じる
First line.
Second line.
```

### raw文字
- 「\」を前置した文字が特殊文字に解釈されるのを防ぐには**raw文字列**を使う

```python
>>> print('C:\some\name') # \n は改行なので
C:\some
ame
>>> print(r'C:\some\name') # 引用符の前のr に注目
C:\some\name
```

### トリプルクォート
- 文字列リテラルを複数行にわたり書くこともできる
  - トリプルクォート（"""..."""または'''...'''）を使う
  - 行末文字が自動的に文字列に含有されるのを避けるには行末に`\`を置く

```python
# 以下のようにすると
print("""\
Usage: thingy [OPTIONS]
-h Display this usage message
-H hostname Hostname to connect to
""")

# 以下のような出力が得られる（最初の改行が含まれていないことに注目）
Usage: thingy [OPTIONS]
-h Display this usage message
-H hostname Hostname to connect to
```

### 文字列の連結
- 文字列は`+`演算子で連結でき、`*`演算子で繰り返すことができる

```python
# un を3 回繰り返して最後にium を付ける
>>> 3 * 'un' + 'ium'
'unununium'
```

- 列挙された文字列リテラル（引用符で囲まれたものたち）は自動的に連結される
- 長い文字列を分割したい時に便利
  - リテラル同士でのみ有効で、変数や式では無効

```python
>>> 'Py' 'thon'
'Python'
>>> text = (' カッコの中にながいながいながい文字列を'
' 入れておいて繋げてやろう。')
>>> text
' カッコの中にながいながいながい文字列を入れておいて繋げてやろう。'
```

- 変数とリテラルの連結、そして変数同士の連結には`+`を使う

```python
>>> prefix = 'Py'
>>> prefix + 'thon'
'Python'
```

### インデックス
- 文字列は**インデックス指定**（連番による指定）ができる
  - 最初のキャラクタは0
  - ここでいうキャラクタは長さが1の文字列のこと

```python
>>> word = 'Python'
>>> word[0] # 位置0 のキャラクタ
'P'
>>> word[5] # 位置5 のキャラクタ
'n'
```

- インデックスには負の数も使え、右から数えることを示す
- -0は0と同じなので負のインデックスは-1から始まる

```python
>>> word = 'Python'
>>> word[-1] # 最後のキャラクタ
'n'
>>> word[-2] # 最後から2 番目のキャラクタ
'o'
>>> word[-6]
'P'
```

- 大きすぎるインデックスを指定するとエラーになる

```python
>>> word[42] # word は6 文字
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: string index out of range
```

### スライシング
- インデックスを使うと個々の文字が取得できるのに対し、スライシングでは部分文字列が取得できる

```python
>>> word = 'Python'
>>> word[0:2] # 位置0 から（0 を含み）2 まで（2 を含まない）の文字
'Py'
>>> word[2:5] # 位置2 から（2 を含み）5 まで（5 を含まない）の文字
'tho'
```

- 始点は常に含まれ、終点は常に除外されることに注目
- これにより`s[:i] + s[i:]`は常に`s`と等価となる

```python
>>> word = 'Python'
>>> word[:2] + word[2:]
'Python'
>>> word[:4] + word[4:]
'Python'
```

- 第一文字の省略時デフォルト値が0
- 第二文字の省略時デフォルト値が文字列のサイズ

```python
>>> word = 'Python'
>>> word[:2] # 最初の文字から位置2（2 を含まない）までの文字
'Py'
>>> word[4:] # 位置4（4 を含む）から最後までの文字
'on'
>>> word[-2:] # 位置-2（含む）から最後までの文字
'on'
```

- スライシングの覚え方
  - **インデックスとは文字と文字の「間」を指す数字**
  - **最初の文字の左端が0になっている**
  - **n文字からなる文字列の最後の文字の右がインデックスnとなる**
  - **インデックスiからjまでのスライシング`[i:j]`は境界iと境界jに挟まれた文字すべてからなる**
  - **非負のインデックスにおいて、スライシングの長さは2つのインデックスの差となる（word[1:3]の長さは2）**

```text
 +---+---+---+---+---+---+
 | P | y | t | h | o | n |
 +---+---+---+---+---+---+
 0   1   2   3   4   5   6
-6  -5  -4  -3  -2  -1
```

- スライシングでは範囲外のインデックスを指定しても、いい具合に処理してくれる

```python
>>> word = 'Python'
>>> word[4:42]
'on'
>>> word[42:]
''
```

### 変更不能体（immutable）
- Pythonの文字列は改変できないため、文字列のインデックス位置に代入を行うとエラーが出る

```python
>>> word = 'Python'
>>> word[0] = 'J'
...
TypeError: 'str' object does not support item assignment
>>> word[2:] = 'py'
...
TypeError: 'str' object does not support item assignment
```

- 異なる文字列が必要なときは新しい文字列を生成する必要がある

```python
>>> word = 'Python'
>>> 'J' + word[1:]
'Jython'
>>> word[:2] + 'py'
'Pypy'
```

## リスト
### 概要
- Pythonには複合したデータのための型がいくつかあり、他の種類の値をまとめるのに使える
- もっとも万能なのがリストで、角括弧の中居にカンマ区切りの値（アイテム）を入れる
- リストには異なる型のアイテムを入れられるが、通常はすべて同じ型を入れる

```python
>>> squares = [1, 4, 9, 16, 25]
>>> squares
[1, 4, 9, 16, 25]
```

### インデックスとスライシング
- 文字列同様（他のすべてのシーケンス型同様）、リストにはインデックスとスライシングが使える

```python
>>> squares = [1, 4, 9, 16, 25]
>>> squares[0] # インデクシングはアイテムを返す
1
>>> squares[-1]
25
>>> squares[-3:] # スライシングは新たなリストを作って返す
[9, 16, 25]
```

- スライシングへの代入も可能
- リストの長さを変えたり、リストの内容をすべてクリアすることができる

```python
>>> letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g']
>>> letters
['a', 'b', 'c', 'd', 'e', 'f', 'g']
>>> # いくつかの値を置換
>>> letters[2:5] = ['C', 'D', 'E']
>>> letters
['a', 'b', 'C', 'D', 'E', 'f', 'g']
>>> # これらを削除
>>> letters[2:5] = []
>>> letters
['a', 'b', 'f', 'g']
>>> # リストをクリア。空リストで全部の要素を置換する
>>> letters[:] = []
>>> letters
[]
```

- スライシング操作は常に、要求された要素を含んだ新たなリストを返す
- 以下のスライシングはシャローコピーを新しく作って返す動きとなる

```python
>>> squares = [1, 4, 9, 16, 25]
>>> squares[:]
[1, 4, 9, 16, 25]
```

### リストの連結
- リストは連結などの操作もサポートしている

```python
>>> squares = [1, 4, 9, 16, 25]
>>> squares + [36, 49, 64, 81, 100]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
```

### 変更可能体（mutable）
- 文字列は変更不能体（immutable）だったが、リストは**変更可能体（mutable）**、すなわち内容を入替えることができる

```python
>>> cubes = [1, 8, 27, 65, 125] # どこかおかしい
>>> 4 ** 3 # 4 の3 乗は64 だ。65 じゃない！
64
>>> cubes[3] = 64 # まちがった値を入れかえる
>>> cubes
[1, 8, 27, 64, 125]
```

### アイテムの追加
- `append()`メソッドを使うことでリストの末尾にアイテムを追加できる
```python
>>> cubes = [1, 8, 27, 64, 125]
>>> cubes.append(216) # 6 の3 乗を追加
>>> cubes.append(7 ** 3) # 7 の3 乗を追加
>>> cubes
[1, 8, 27, 64, 125, 216, 343]
```

### リストの入れ子
- リストは入れ子にすることができる

```python
>>> a = ['a', 'b', 'c']
>>> n = [1, 2, 3]
>>> x = [a, n]
>>> x
[['a', 'b', 'c'], [1, 2, 3]]
>>> x[0]
['a', 'b', 'c']
>>> x[0][1]
'b'
```

## 用語
### リテラル
- 定数などのように数値や文字列の実際の値が単に記述されているもののこと

### シーケンス型
- 複数の要素から構成されるもので、要素が順番に並んでいるもの（リスト等）

### シャローコピー
- オブジェクトの複製を伴わないポインタのコピーのこと