初心者向けPython3勉強会：型

# 初心者向けPython3勉強会：型

### 諸注意

* 本稿はJava（か、それ以外の言語）をかじっている同期に向けて、他言語とPythonの違いにフォーカスして作成しております
* 作成にあたって、[Python リファレンス](https://docs.python.org/ja/3/reference/index.html)をベースにしております
* 初心者向けに[チュートリアル](https://docs.python.org/ja/3/tutorial/index.html)も公開されております、詳細を理解しながら学習したい方にオススメです
* Pythonはユニークな特徴をたくさん持っています。全て一度に説明すると取っ掛かりにくい部分もありますので、必要なものを必要なときに説明していきます
* 執筆時のバージョンは`Python 3.7.3`です
<br>

## はじめに
Pythonは「読みやすく、書きやすい」プログラミング言語です。そのため多くのユーザは、単純で短い簡潔コードをよしとする傾向が強いです
とはいえ、最初から簡潔なコードを目指すと苦労することが多々あります。なぜならば、Pythonは「読みやすく、書きやすい」プログラミング言語であるがために、独特な記法による記述が多いためです
以下に、はじめに気をつけるべきPythonの記法・性質について説明します
<br>

### ブロックの記述方法
Javaなどでは、if文やfor文といったブロックを、中括弧`{}`で囲んで記述していたかと思います
Pythonでは中括弧は使わず、インデントを使用してブロックを記述します
このように、インデントが構文規則定められている規則を **オフサイドルール** と言います
詳しくはif文、for文の説明にの際に、併せて解説します
<br>

### 変数宣言
Pythonは **動的型付け(dynamic typing)** を行う言語です
動的型付けとは、プログラムの実行時に型が決定されることを言います
Javaでは変数を宣言するたびに型を定義する必要がありましたが、Pythonではその必要はありません
<br>

### オブジェクトと型の違い
Pythonでは、クラスも関数も変数も配列も型も、全てがオブジェクトです
とはいえ、最初からそれを意識しながら学習する必要はありません。なので、この章で扱うものは便宜上"型"と呼ぶことにします
（コメント欄でご指摘いただいている話はここにつながります、これに関しては後ほど説明します）
<br>

## 演算
Pythonでは他の言語と同じように、演算子や関数を用いてが様々な演算が行えます
今回は算術演算、ブール演算、比較演算の方法とその結果を紹介します

### 算術演算 

| 演算 | 結果 |
| :---: | :--- |
| +   | 和 |
| -   | 差 |
| *   | 積 |
| /   | 商 |
| //  | 切り捨て除算 |
| %   | 剰余（除算の余り、mod）|
| **  | 累乗（x^y） |

優先度は`**` > `*, /, //, %` > `+, -`になります

```python
x, y = 10, 3
print("x + y =",  x+y)
print("x - y =",  x-y)
print("x * y =",  x*y)
print("x / y =",  x/y)
print("x // y =", x//y)
print("x % y =",  x%y)
print("x ** y =", x**y)

# 出力結果
x + y = 13
x - y = 7
x * y = 30
x / y = 3.3333333333333335
x // y = 3
x % y = 1
x ** y = 1000
```
<br>

### ブール演算

Pythonにおけるブール演算は、`or`，`and`，`not`の３種類です

| 演算 |
| :-: |
| or  |
| and |
| not |
<br>

### 比較演算

Pythonにおける比較演算子は以下の通りです

| 演算 | 意味 |
| :--- | :--- |
| <   | 小なり |
| >   | 大なり |
| <=  | 小なりイコール |
| >=  | 大なりイコール |
| ==  | 値が等しい |
| !=  | 等しくない |
| is  | 同一のオブジェクト |
| is not  | 異なるオブジェクト |
| in  | 含まれている |
| not in | 含まれていない |

`is`と`in`の詳細については別稿で説明をします
また、Pythonでは比較演算子を連続して書けます

```python
x = 10
y = 20

print(5<x<15)
# > True

print(10<y<=20)
# > True

print(20>(x+y)>10)
# > False
```
<br>


## 数値型

### int型
整数を扱う型です。扱える値の範囲ですが、Pythonのintでは論理的な制限がありません
ただし、「確保可能なメモリサイズまで」といった物理制限はあります
shortやlongといった型もなく、Pythonにおける整数型が全てintで表現できます

```python
x = 10
y = 20
z = a + b

print(z)
# > 30

z = 10**1000000
# print(z)とかすると、楽しいことになります
```
<br>

### bool型
boolは真理値を扱う型です。TrueとFalseの２値をとります
Pythonにおいてboolはintの派生系で、Trueは1、Falseは0として扱われます
文字列に変換すると、`True`、`False`といった形で表されます
Javaと違って、単語のはじめの文字が大文字になることに注意してください

```python
x = 10
y = 20

print(x<y)
# > True

print(x>y)
# > False

z = True
print(z)
# > True

z = False
print(z)
# > True

z = True + True
print(z)
# > 2

z = True - True
print(z)
# > 0
```
<br>

### float型
floatは小数を扱う型です
Javaで小数を表す場合は、floatかdoubleを用います、それぞれ32bit,64bitの浮動小数点数を扱う型です
Pythonではfloatが64bitの浮動小数点数になります。すなわち、doubleと同じです

```python
a = 3.2
b = 6.4

print(a+b)
# > 9.600000000000001

print(a-b)
# > -3.2

print(a*b)
# 20.480000000000004

print(a/b)
# > 0.5
```
<br>

### complex型
複素数型です、実部と虚部はそれぞれfloatで表現されます
`.real`,`.imag`を用いることにより、実部と虚部をそれぞれ抜き出すことができます

```python
a = 2+1j
b = 3-4j

print(a+b)
# > (5-3j)

print(a-b)
# > (-1+5j)

print(a*b)
# > (10-5j)

print(a/b)
# > (0.08+0.44j)

print(a.real, b.imag)
# > 2.0 -4.0
```
<br>

## コンテナオブジェクト
`str`,`list`,`tuple`,`dict`,`range`は、**コンテナオブジェクト**と呼ばれ、複数のオブジェクトをまとめることができます
Javaでいう配列やリストがこれにあたります。ただし、Javaの配列と違い、**動的確保**をすることができます
`list`は`[]`、`tuple`は`()`、`dict`は`{}`、でそれぞれ定義できます
> **動的確保** ：配列などを宣言する際に、変数などを用いて宣言する方法です
> 変数の値に応じて配列の大きさを設定できます
<br>

### str型
String型です、配列としても扱うことができます
Pythonにはchar型が存在しないので、String型の文字列は、１文字のString型による配列として表現されます
また、`+`で文字列の結合を行うことができます
シングルクォーテーションかダブルクォーテーションで囲うとString型になります、クォーテーションによる区別はありません
ただし、String宣言時とは異なるクォーテーションを文字列に含める場合、エスケープせずに出力することができます
> JavaではString型はダブルクォーテーションで表現されます
> そのため、文字列の中にダブルクォーテーションがあると、正しく出力されません
> ダブルクォーテーションを出力したい場合は、エスケープをすることによって、文字列として扱うことができます
> 大概、エスケープしたい文字の前にバックスラッシュを置けばエスケープできます
> 例：System.out.println("Rafaelは\"Hello, world!\"と声高らかに叫んだ")
> 　　\> Rafaelは"Hello, world!"と声高らかに叫んだ

```python
text = 'Hello, world!'

print(text)
# > Hello, world!

print(text + ' Good night!')
# > Hello, world! Good night!

print("Rafaelは\"Hello, world!\"と声高らかに叫んだ")
# > Rafaelは"Hello, world!"と声高らかに叫んだ

print('Rafaelは"Hello, world!"と声高らかに叫んだ')
# > Rafaelは"Hello, world!"と声高らかに叫んだ
```
<br>

### list型
listはコンテナオブジェクトの中でも最もシンプルな型です、ミュータブルなシーケンス型で、中に格納される値は型が違っても問題ありません
> **ミュータブル** ：定義したあとでも値が変えられる
> **シーケンス型** ：配列や文字列など、順番のある要素の集まり

中に格納された値を**要素**、要素が格納されている場所を指す値を**添字**（インデックス）と呼びます
添字は基本的に前から数えた順番で表現しますが、負の値を用いた場合、後ろから数えた順番になります

```python
line = [0,1,2,3,4,5]

print(line)
# > [0,1,2,3,4,5]

print(line[2])
# > 2
print(line[-2])
# > 4

line[3] = 10
print(line)
# > [0,1,2,10,4,5]

line = ['apple', 'banana', 'chocolate']

print(line)
# > ['apple', 'banana', 'chocolate']
print(line[1])
# > banana
print(line[-1])
# > chocolate

line = [2019, '年', 5, '月', 1, '日']
print(line)
# > [2019, '年', 5, '月', 1, '日']
```

listは**スライス操作**が使えます  
line[start:goal]と書くと、i以上j未満の要素を取り出すことができます。このとき、iまたはjは省略することが可能です
また、拡張スライス操作といった機能もありますが、別稿で説明をします

```python
line = [0,1,2,3,4,5]

print(line)
# > [0,1,2,3,4,5]

print(line[1:4])
# > [1,2,3]

print(line[2:])
# > [2,3,4,5,6]

print(line[:3])
# > [0,1,2]

print(line[:])
# > [0,1,2,3,4,5]
```

listの扱いについては、for文や内包表記を説明する際に併せて説明します
<br>

### tuple型
tupleはイミュータブルなシーケンス型です、listがイミュータブルになった、というイメージで今は問題ありません
> **イミュータブル** ：定義したあとに値が変更できない


```python
vect = (3, 6)

print(vect)
# > (3, 6)

print(vect[1])
# > 6

vect[1] = 4
# > Traceback (most recent call last):
# >   File "<stdin>", line 1, in <module>
# > TypeError: 'tuple' object does not support item assignment
```
<br>

### dict型
dictはミュータブルなマッピング型です
> **マッピング型** ：キーと値が対応づけられている配列、ディクショナリー配列、連想配列とも呼ばれる

listやtupleと違い、要素を`key`と`value`で紐づけます。`key`が添字、`value`が値です  
また、辞書・連想といった単語からわかるように、dictは`key`から`value`を取り出すことができます

```python
price = {'apple':80, 'banana':120, 'chocolate':100}

print(price['apple'])
# > 80

print(price['chocolate'])
# > 100

price['water'] = 70
print(price['water'])
# > 70
```

また、dictでは`key`が添字となるため、`key`はイミュータブルであるべきです
よって変数などを`key`として使用しないことが望まれます
`value`ではそのような制約はないですが、少し複雑な構成になります

```python
fruit = 'banana'
v = 80
price = {'lemon':v, 'water':60, fruit:120}

print(price['lemon'])
# > 80

v = 100
print(price['lemon'])
# > 80

print(price[fruit])
# > 120

fruit = 'apple'
print(price[fruit])
# > Traceback (most recent call last):
# >   File "<stdin>", line 1, in <module>
# > KeyError: 'apple'
```

`value`に変数を使用し後から値を変更すると、dictに結果が反映されます、これは`dict['lemon']`に直接`v`が入っているためです
しかし`fruit`の変更は容認されません
これは`fruit = 'banana'`より`fruit:120`が`'banana':120`と置き換えられるからです
そのため、`fruit = 'apple'`と代入してしまうと、`price[fruit]`が`price['apple']`に置き換えられ、`key`が存在しないためエラーとなってしまいます
<br>

### range
rangeはイミュータブルなシーケンス型で、主にfor文などのループに使われます
整数の等差数列のリストを生成することができる組み込みメソッドです
`range(i,j)`と書くと、listのスライス操作と同じように数列を表現できます
また、最初の値（上例では`i`）を省略すると自動的に`0`が代入されます

```python
# range自体はメソッドなので、中身を見たい場合はlistにキャストします
print(list(range(0,10)))
# > [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

print(list(range(10)))
# > [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

print(list(range(4,12)))
# > [4, 5, 6, 7, 8, 9, 10, 11]
```

また、rangeは[拡張スライス操作](https://qiita.com/m_rafa0110/items/e1fbcf04ee808ccb8e18#拡張スライス操作)と同じようにステップ数も設定できます


## おわりに
以上が、Pythonで一般的に使われる型の説明です
今回は型の性質を説明するため話をだいぶ省略していますが、Pythonらしい面白い機能がたくさん備わっています
特にコンテナオブジェクトでは、**内包表記**といったPython独自の記述方法があります、是非覚えていきましょう！

また、本稿について不明点・修正点などございましたら、何卒コメントをよろしくお願いいたします

# 人生苦短我用Python!!