Pythonはじめました

# はじめに

Pythonの基本的な書き方を記載します。
バージョンは3.4.3です。

#コメント
コメントは "#" ではじまります。

```py3
# これはコメントです
```

# 数値

整数、浮動小数点数、複素数があります。

```py3
# 四則演算
2 + 3 # 5
2 - 3 # -1
2 * 3 # 6

# 整数の割り算は浮動小数点数になります
2 / 3 # 0.6666666666666666

# //演算で割り算後の整数部分が取り出せます
3 // 2 # 1

# **はべき乗です
2 ** 10 # 1024 2の10乗

# 複素数
(1+1j) + (2+2j) # (3+3j) 虚数単位はj、1jの1は省略不可
c = 1 + 2j
c.real #1.0 実部
c.imag #2.0 虚部
```

# sequence

要素が番号順に並んだデータ構造です。
各要素は0からはじまる整数indexでアクセス可能です。

次のデータ構造はsequenceです。

+ 文字列
+ list
+ tuple
+ range

Listを例にしてsequenceを説明します。

```py3
l = [1,2,3]
l[0]        # 1 要素0 indexは0ではじまる
l[2]        # 3 要素2
l[-1]       # 3 要素3 indexはマイナスでもOK
len(l)      # 3 要素数
max(l)      # 3 最大値
min(l)      # 1 最小値
l.count(1)  # 1 出現回数
1 in l      # True  要素が含まれるかどうか
3 in l      # False 
1 not in l  # False 要素が含まれないか、inの真偽反転

# 範囲を指定してListを返します
l[:]        # [1,2,3] 全要素をListで返す
l[1:2]      # [2]     a:b形式でaからb-1までの要素をListで返す
l[0:]       # [1,2,3] a:形式でaから最後までの要素をListで返す
l[:2]       # [1,2]   :b形式で先頭からb-1までの要素をListで返す
```

## 文字列
要素が文字であるsequenceです。
要素の変更はできません。

```py3
s = "string" # 文字列は"でくくる
s = 'string' # 'でもOK

# 整数indexで文字にアクセスできます
s[0] # 's'

# 要素は変更できません
s[0] = "S" # エラー

# 複数行の文字列は" or 'を3個並べたものでくくります
'''
複数行の
文字列
'''

# 文字列をつなげます
"a" + "b" # 'ab'

# 文字列を繰り返します
"a" * 2 # 'aa'

# 文字列を分割します
"1,2".split(",") # ['1', '2'] リストが返る

# 文字列を結合します
",".join(["1","2"]) # '1,2'

# 文字列を数値に変換します
int("0x10", 16) # 16 第2引数は基数
int("10")       # 10 第2引数を省略すると基数10扱い
int("10", 2)  　# 2
float("1.2")    # 1.2

# 数値を文字列に変換します
"dec:{0},hex:{0:X},bin:{0:b}".format(16) # 'dec:16,hex:10,bin:10000'
"{0:.2f}".format(3.1415) # '3.14'
```

## list
任意のデータを要素にできるsequenceです。
要素を変更できます。

```py3
l = [1,2,3] # ,区切り、"[]"でくくる
l[0]        # 1 要素0 indexは0ではじまる
l[2]        # 3 要素2
l[-1]       # 3 要素3 indexはマイナスでもOK

# 末尾に要素を追加します
ll = l + [4] # ll = [1,2,3,4] 要素を追加します(+)
l.append(4)  # l  = [1,2,3,4] 要素を追加します(append)

# 末尾から要素を取り出します
l = [1,2,3]
l.pop # 3 結果 l = [1,2]

# 要素の繰り返しを返します
l = [2]
l * 2  # [2,2]

# リストの初期化には内包表記というものが使えます
# []内にfor文を記載します
l = [x for x in range(10)] # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# 多次元リスト
# 2次元:行列
m = [[row for row in range(2)] for col in range(3)] # [[0, 1], [0, 1], [0, 1]]
# 3次元
m = [[[row for row in range(2)] for col in range(3)] for mat in range(4)]
```

## tuple
任意のデータを要素にできるsequenceです。
**要素を変更できません。この点がListとの違いです。**

```py3
t = (1,2,3) # ,区切り、"()"でくくる
t[0] = 10   # エラー、要素を変更できない
```

## range
数値を要素にできるsequenceです。
要素を変更できません。for文と組み合わせて使います。

```py3
# range(x)で0~x-1を表します
# 0~9が表示されます
for i in range(10):
	print(i)
	

# range(x, y)でx~y-1を表します
# 1~9が表示されます
for i in range(1, 10):
	print(i)
	

# range(x, y, step)でx,x+step, x+2*step, ... (y-1まで)を表します。
# 1,3,5,7,9を表します。
for i in range(1, 10, 2):
	print(i)
	
```

# 制御文

## if
` aaa < x < bbb`形式で比較条件が指定できます。
`in`や`is`演算が使用できます。

```py3
# if .. elif .. else
x = 1
if x == 1:
	print("x == 1")
elif x == 2:
	print("x == 2")
else:
	print("else")
# result : x == 1

# < x < 演算
x = 5
if 1 < x < 6:
	print("True")
else:
	print("False")
# result : True

# in 演算
if 0 in [1, 2, 3]:
	print("True")
else:
	print("False")
# result : False

# not in 演算
if 0 not in [1, 2, 3]:
	print("True")
else:
	print("False")
# result : True

# is 演算、同じオブジェクトかどうかを判断します
if [1] is [1]:
	print("True")
else:
	print("False")
# result : False

l = [1,2,3]
ll = l
if l is ll:
	print("True")
else:
	print("False")
# result : True
```

## for
break/continueは他の言語と同じです。
elseが特徴的です。for文を最後まで実行したときにelseが実行されます。
breakで止まった時はelseは実行されません。

```py3
# range
for i in range(10):
	print(i)
# result : 0~10

# list
for i in [1, 2, 3]:
	print(i)
# result : 1~3

# else/break
# elseをつけることができます。
# 最後までforを実行したときにelseが実行されます。
# breakしたときには実行されません。
for i in [1, 2, 3]:
	print(i)
	if i == 2:
		break
else:
	print("else")
# result : 1~2, elseは表示されない
```

## while
forと同じくelseをつけることができます。

```py3
i = 0
while i < 10:
	print(i)
	if i == 1:
		break
	i = i + 1
else:
	print("else")
# result : 0~1
```

# 関数
`f(x=10, y=20)`など引数名を指定して関数を呼び出せます。
可読性がよくなり、引数順番を変えられます。

```py3
# 合計値を返す関数を定義します
def sum(l):
	val = 0
	for i in l:
		val = val + i
	return val
	
print(sum([1, 2, 3]))
# result : 6

# default引数を指定できます
def add(x=10, y=20):
	return x + y
	
print(add())
# result : 30

# 引数名を指定して呼び出せます、引数順番を変えられます。
def sub(x, y):
	return x - y
	
print(sub(y=20, x=10))
# result : -10
```

# モジュール

クラスや関数が記載されたファイルをモジュールといいます。
拡張子は.pyです。モジュール名は.pyを除いたファイル名です。
よく使う機能をモジュールにまとめておくと再利用ができて便利です。

```py3
# importでモジュールを取り込みます。
import numpy as np # as で別名を定義
a = np.array([1,2,3]) # 別名 npでモジュールメンバを参照する

# 単にimportしたときにはモジュールメンバを参照するときには
# モジュール名(or別名)で修飾(e.g. np.array)する必要があります。
# fromを使うことで修飾を省略することができます。
from numpy import array
a = array([1,2,3]) # npなしでOK

# *ですべて指定することも可能
from numpy import *
```

# クラス
クラスを定義すると対応するクラスオブジェクトが作成されます。
コンストラクタ名は`__init__`です。引数にselfをとります。
selfとは自分自身のオブジェクトを参照するためのキーワードです。

クラスオブジェクトは以下を含みます

- クラス変数
- インスタンス変数
- クラスメソッド
- インスタンスメソッド
- スタティックメソッド

変数とメソッドはパブリック、プライベートスコープを持ちます。
名前の先頭に`__`をつけるとプライベートになります。
プライベートなものはクラス外からはアクセスできません。

```py3
# クラスを定義します
class Test:
    # クラス変数
    i   = "pub class var" # パブリック
    __i = "prv class var" # プライベート
    
    # インスタンスメソッド
    def method(self):
        print("pub inst method")
    
    def __method(self):
        print("prv inst method")
        
    # クラスメソッド
    @classmethod
    def cls_meth(cls):
        print("cls_meth")
    
    # スタティックメソッド
    @staticmethod
    def stat_meth():
        print("stat_meth")
    
    # コンストラクタ
    def __init__(self):
        # インスタンス変数
        self.j   = "pub inst var" # パブリック
        self.__j = "prv inst var" # プライベート
        
        print("__init__")
        # パブリック
        print(Test.i)   # クラス変数       class.name形式
        print(self.i)   # クラス変数         obj.name形式
        print(self.j)   # インスタンス変数   obj.name形式
        self.method()   # メソッド
        
        # プライベート
        print(self.__i) # クラス変数       class.name形式
        print(self.__j) # インスタンス変数   obj.name形式
        self.__method() # メソッド

# インスタンスを作成します
t1 = Test()
t2 = Test()

# 変数を参照します
print(Test.i) # 1 クラス変数  class.name形式
print(t1.i)   # 1 クラス変数  obj.name形式
print(t1.j)   # 2 インスタンス変数  obj.name形式

# 同じ名前のクラス変数、インスタンス変数が定義できます
# 混乱のもとなのでこのような使い方はしないようがいいです
t1.i = 10
print(t1.i)   # 10 obj.nameを優先して取得します。t1からはクラス変数iを参照できません
print(Test.i) # 3
print(t2.i)   # 3

# 動的な変数追加
t1.x = 10    # 動的にインスタンス変数を追加できます。
print(t1.x)  # 10
del t1.x     # 削除します
Test.x = 20   # 動的にクラス変数を追加できます。
print(Test.x) # 20
del Test.x    # 削除します

# メソッドを呼び出します
t1.method()
#t1.__method() # エラー

# クラスメソッド呼び出し
Test.cls_meth()

# スタティックメソッド呼び出し
Test.stat_meth()
```

## 継承
クラス定義で`class Child(Parent)`と記述することで
Parentを継承するChildクラスが定義できます。

子クラスから親クラスのプライベートメンバにはアクセスできません。
親クラスのメソッドを子クラスからオーバーライドできます。
親クラスのインスタンス変数を定義するには、子クラスのコンストラクタで
親クラスのコンストラクタを呼び出す必要があります。

```py3
# 親クラスを定義します
class Parent:
    i   = "pub class var"
    __i = "prv class var"

    def __init__(self):
        self.j   = "pub inst var"
        self.__j = "prv inst var"

    def meth(self):
        print("pub inst meth")
        print(self.i)
        print(self.__i)
        self.__meth()

    def meth2(self):
        print("pub inst meth2")
        print(self.j)
        print(self.__j)

    def meth3(self):
        print("pub inst meth3")

    def __meth(self):
        print("prv inst meth")

# 子クラスを定義します
class Child(Parent):
    def __init__(self):
        # 親クラスのコンストラクタを呼びます
        # これをなくすと親クラスのインスタンス変数が定義されません
        # 子クラスからのmeth2がエラーになります
        Parent.__init__(self) 

    # overrideします
    def meth3(self):
        print("child pub inst meth3")

    def meth4(self):
        self.__meth()

# インスタンスを作成します
p = Parent()
p.meth()
p.meth2()
p.meth3()
c = Child()
c.meth() 
c.meth2() 
c.meth3() # 子クラスのmeth3が呼ばれます
#c.meth4()
# エラーになります
# 子クラスから親クラスのプライベートメソッドにはアクセスできません
```

# 例外

```py3
try:
	int("xxx") # 数値でないため例外発生
except OSError:
	print("OSError")
except ValueError:
	print("ValueError")
# resutl : ValueError

# 例外なしの場合はelseが実行されます
try:
	int("10")
except OSError:
	print("OSError")
except ValueError:
	print("ValueError")
else:
	print("NoError")
# resutl : NoError

# 例外があってもなくてもfinallyが実行されます
try:
	int("xxx")
except OSError:
	print("OSError")
except ValueError:
	print("ValueError")
finally:
	print("Finally")
# resutl : ValueError Finally
```

# ファイル

```py3
# withを使うと例外が発生しても正しくcloseできます
with open("tmp.txt", "a") as f:
	f.write("test\n")

# for文を使うとすべての行に対して処理できます
with open("tmp.txt", "r") as f:
	for ln in f:
		print(ln)
```

# コマンドライン引数
コマンドライン引数はsys.argvに入ります。
sys.argv[0]はスクリプト名です。
sys.argv[1]が第1引数となります。

```py3:test.py
import sys
print(sys.argv)
```

```
>python test.py param1 param2
['test.py', 'param1', 'param2']
```

# 正規表現

```py3
import re

ln = "<tag>1234</tag>"
# 正規表現を定義します。()でグルーピングできます。
r = re.compile("<tag>(.+)</tag>")
# 検索します。
m = r.search(ln)
# マッチしなければmはNoneになります
print(m.group(0)) # マッチした文字列全体です "<tag>1234</tag>"
print(m.group(1)) # ()でグルーピングした文字列が返ります。 "1234"
```