ソースコードで学ぶWebプログラミング

Pythonプログラミングの基礎

人工知能の開発や機械学習で取り上げられることが多いプログラミング言語に、Pythonがあります。Pythonには、numpyやpandas、matplotlibなどのデータ処理を簡単に行えるライブラリが存在します。いずれもインストールが必要ですが、Anacondaと呼ばれるディストリビューションでまとめてインストールが可能です。詳細は、公式サイトなどをご覧ください。

Pythonでは、Python2、Python3と仕様の異なるバージョンが使われています。このページではPython3を対象に、初学者用に基礎事項を簡単に説明します。

Pythonの変数について

Pythonの変数には、数値型、文字列型、シーケンス型(リスト、タプル)、辞書型(連想配列)などがあります。またブロック内のローカル変数、グローバル変数の違いがあります。変数名は、英数字とアンダースコアで付けることができ、大文字と小文字で区別されます。

Pythonでは、変数名の付け方には注意が必要で、標準で利用できる関数(組み込み関数)と重複した場合でもエラーにはならず、上書きされてしまいます。

またPythonでは、定数を定義することが出来ないため、慣習的に英字とアンダースコアの組み合わせのみで定義された変数を定数とします。

# コメント # 標準ライブラリの読み込み import モジュール名 # ライブラリの一部を読み込む from モジュール名 import クラス名、メンバ名 # モジュール名を別名にする import モジュール名 as 別名 # 変数名の先頭は 英字、アンダースコア _tmp1 = [] # 先頭に数字は使えない エラー 1tmp = [] # 標準関数が上書きされる str = 'abc' # 大文字と小文字で別の変数になる A = 'A' a = 'a' # グローバル変数 v = 1 def func(): # ローカル変数 v = 2 return v print(func()) #2 print(v) #1 # グローバル変数 v = 1 def func(): # グローバル変数 global v v = 2 return v print(func()) #2 print(v) #2 # 変数の型を確認 print(type(x)) # 変数の中身を整形して表示 from pprint import pprint pprint(x) # 定数の慣習的表現 DB_NAME = ''

Pythonで文字列を扱う方法

Pythonでは、文字列でもs[1]のように添字表記や、s[1:2]のようにスライス表記が可能です。また * 演算子で反復文字を表現できます。

# 文字列の結合 s = 'a'+'b' s += 'c' s = 'a' 'b''c' #空白や空白がなくても結合可 # 数値と文字列を結合 s = 'a' + str(10) #型変換 s = '{0}月{1}日'.format(12, 31) # 文字列の繰り返し s = 'a' * 5 #aaaaa # 文字列の一部取り出し [開始、終端(未満)、飛ばし間隔] s = 'abcdef'[2] #c s = 'abcdef'[1:3] #bc s = 'abcdef'[::2] #ace # 文字列の反転 s = '0123456789'[::-1] #9876543210 # 文字列をすべて置換 s = 'ababab'.replace('a','c') #cbcbcb # 文字列を一部置換 s = 'ababab'.replace('a','c',1) #cbabab # 文字列を正規表現で置換 import re s = re.sub('\d','','s1t2r3i4n5g6') #string # 大文字を小文字に s = 'AbCdEf'.lower() #abcdef # 小文字を大文字に s = 'AbCdEf'.upper() #ABCDEF # 文字列の長さ n = len('aaa') # 文字列の比較 if s=='': # 文字列を正規表現で判定 import re m = re.search("[^\d]+",s) # 数値以外 # 変数を特定のフォーマットで表示 m = 9 s = '{:02d}月'.format(m) # 文字列内で変数を展開 s = 'ABC' s = 'テキスト%s文字列' % s # 文字列を配列(リスト)に a = '1 2 3'.split() #['1','2','3'] a = 'a,b,c,d'.split(',') #['a','b','c','d']

Pythonで配列(リスト)、連想配列(辞書)を扱う方法

Pythonでは、プログラミング言語の概念である配列に相当するものとして、リストがあります。また要素を変更できないリストがあり、タプルと呼びます。リストは[]で作成し、タプルは()で作成します。Pythonで連想配列に相当するものに、辞書があります。

配列とは、複数の数値や文字列が代入されている入れ物で、要素に並び順があります。並び順であるインデックス(数値)で値を取得することが出来ます。配列には、先頭から順番にもれなく処理できる利点があります。配列の要素として、配列や辞書を入れることも出来ます。

# リストを作成 li = [0,1,'3'] li = [0] * 5 #[0,0,0,0,0] li = list('abcde') #['a','b','c','d','e'] li = list(range(5)) #[0,1,2,3,4] li = list(range(5,10)) #[5,6,7,8,9] # 条件式で作成 偶数 li = [i for i in range(10) if i%2==0] #[0,2,4,6,8] # リストから取り出し v = li[1] # リストを結合 li = ['A','B','C'] + ['D','E'] # リストの最後に要素を追加 li = ['A'] li.append('B') # リストの最後にリストの要素を追加 li.extend(['C','D']) # リストの指定位置に要素を挿入 li = ['A','B','E'] li.insert(2, 'C') #['A','B','C','E'] # リストの指定位置にリストの要素を挿入 li[2:2] = ['C','D'] # リストの最後から除去 li = list('abcde') li.pop() # 最後から除去して取り出し n = li.pop() # 値を指定して削除 li.remove('c') # 要素を削除 del(li[1]) # リストの要素数 n = len(li) # リストを順番に処理 for v in li: print(v) #値 # リスト番号を使う for i,v in enumerate(li): print('インデックス:{}、値:{}'.format(i,v)) # 複数のリストを同時に処理 li1 = list(range(3)) li2 = list(range(5,10)) for v1,v2 in zip(li1,li2): #短いリストの長さ優先 3回処理 print('リストA:{}、リストB:{}'.format(v1,v2)) # リストを指定文字区切りで文字列に s = ','.join(li)

タプルは、要素の変更が出来ない配列です。要素の追加や、要素内の要素については変更することが出来ます。それ以外については、リストと同様に扱うことが出来ます。

# タプルを作成 tu = (1,2,3,4,5) tu = tuple(range(5)) # タプルから取り出し v = tu[1] # タプルの要素を変更 エラーになる tu[1] = 2 # 要素が一つのタプル ,が必要 tu = (1,) # タプルに追加 tu = (1,2,3) tu += ('a','b') # タプルの要素の要素を変更 tu = (1,2,['a','b'],4) tu[2][0] = 'c' #(1,2,['c','b'],4) # タプルをリストに変換 li = list(tu) # リストをタプルに変換 tu = tuple(li) # タプルの要素数 n = len(tu)

連想配列(辞書)は、キーとなる文字列で、対応する値を取り出すことが出来る配列です。連想配列(辞書)には、並び順が存在しないため、順番に処理する場合は、キーの配列を用意する必要があります。

# 辞書を作成 d = {"point":20,"name":"user1"} # キーと値のタプルのリストで作成 d = dict([("k1",10), ("k2","val")]) # 辞書からキーで値の取り出し v = d.get('point') # ↓キーがない時エラー v = d['point'] # .get() と同じ動作 v = d['point'] if 'point' in d else None # 辞書に要素を追加 d['key'] = 'value' # 辞書のキーのリスト li = d.keys() # 辞書の値のリスト li = d.values() # キーと値のタプルのリスト li = d.items() # 辞書の要素数 n = len(d)

Pythonの制御構文

Pythonでは、インデント(字下げ)でブロックを表現するため{}は不要です。条件文の()や行末の;も必要ありません。ステートメントで改行したい場合は()で括ります。また[]や{}内でも改行ができます。

# 条件分岐 if A: Aの時の処理 elif B: Bの時の処理 else: A,B以外の時   # 複数の条件 if A and B: #AかつB if A or B: #AまたはB # 複数の条件で長くなる場合 if (A and B and C): # 変数の定義時に改行 a = [ 0, 1 ] h = { 'a':'A', 'b':'B' } # 3項演算子 v = (trueの時の値) if (条件) else (falseの時の値) v = 1 if 1 else 2 #v=1 # 指定回数ループ処理を行なう for i in range(10): 処理 # 条件が真の時、ループ処理 while A: if B: # 次に飛ばす continue if C: # ループを抜ける break; # 例外処理 try: v = d['key'] except Exception as e: print(e) # 文字列が含まれるか判定 if 'a' in s: # リストに要素が含まれるか判定 if 'a' in li:

Pythonでデータ取得を行なう方法

Pyhonで、ファイルや標準関数からデータを取得する方法です。インポートが必要な処理もありますが、すべて標準ライブラリのため、インストールは必要ありません。CGIなどのWebプログラムでは、環境変数や標準入力からユーザーの入力を受け取ることが出来ます。

# ファイル名の設定 FILE_NAME = 'file.txt' # ファイルから読み込む # 1行ずつ処理 with open(FILE_NAME,'r') as f: for line in f: # すべて読み込んで文字列に with open(FILE_NAME,'r') as f: lines = f.read() # すべて読み込んでリストに with open(FILE_NAME,'r') as f: lines = f.readlines() # ディレクトリ内のファイル一覧 import glob li = glob.glob('*.txt') # ファイル情報 import os info = os.stat('file') # 最終更新日時 mtime = int(info.st_mtime) # 環境変数から取得する import os query = os.environ.get("QUERY_STRING") method = os.environ.get("REQUEST_METHOD") # 標準入力から取得する import sys data = sys.stdin.read() # Unixタイムスタンプを取得する import time # 小数付き t = time.time() # 秒単位に t = int(time.time()) # 日時を取得する from datetime import datetime now = datetime.now() date1 = now.strftime('%Y-%m-%d') date2 = now.strftime('%H:%M:%S') # 曜日 week = ['月','火','水','木','金','土','日'] w = week[now.weekday()] # ランダムな数値を取得する import random r = random.randrange(10) r = random.randrange(50,100) # コマンドラインの引数から取得 import sys args = sys.argv # 外部コマンド実行時の戻り値から取得 import subprocess cmd = 'ls -l' r = subprocess.check_output(cmd.split()) # スクリプトのファイルパス __file__

Pythonでデータ変換を行なう方法

プログラムのメイン処理となる、入力されたデータを出力するために、適切なフォーマットに変換する処理です。コード内のインポートはいずれも標準ライブラリを対象にしています。

#特定の文字列を除去する # カンマを除去 s = s.replace(',','') # タブ文字を除去 s = s.replace("\n",'') # 末尾の改行や空白を除去 s = s.rstrip() # HTMLエスケープする s = s.replace('&','&amp;'); s = s.replace('<','&lt;'); s = s.replace('>','&gt;'); s = s.replace('"','&quot;'); s = s.replace("'",'&#39;'); # 改行コードの統一 s = s.replace("\r\n","\n") s = s.replace("\r","\n") # URLデコード import re s = s.translate({'+':' '}) s = re.sub(b'%([a-fA-F0-9][a-fA-F0-9])',lambda x:bytes([int(x.group(1),16)]),s.encode('utf-8')).decode('utf-8') # URLエンコード s = re.sub(b'([^a-zA-Z0-9 ])',lambda x:('%{:02X}'.format(x.group(1)[0])).encode('utf-8'),s.encode('utf-8')).decode('utf-8') s = s.translate(' ','+') # Shift_JISのCSVファイルを開く import csv with open('***.csv', 'r', encoding='Shift_JIS') as f: for c in csv.reader(f): # CSVファイルをShift_JISで保存する import csv with open('***.csv', 'w', encoding='Shift_JIS') as f: cw = csv.writer(f) cw.writerow(['ID','名前','住所']) # Unixタイムスタンプから日時を取得する from datetime import datetime t = 1546182000 date = datetime.fromtimestamp(t).strftime('%Y-%m-%d %H:%M:%S') # 日時文字列からUnixタイムスタンプを取得する import time from datetime import datetime s = '2018-12-31' t = time.mktime(datetime.strptime(s,'%Y-%m-%d').timetuple()) # 変数を保存用に文字列にする import pickle bi = pickle.dumps(x) # 文字列にした変数を復元する x = pickle.loads(bi) # 変数をファイルに保存する with open('save.dat', 'wb') as f: pickle.dump(x, f) # ファイルに保存した変数を復元する with open('save.dat', 'rb') as f: x = pickle.load(f) # 変数をJSONデータに変換する import json j = json.dumps(x) # JSONデータを変数に変換する x = json.loads(j) # 変数をJSONデータとして保存する with open('save.json', 'w') as f: json.dump(x, f) # 保存したJSONデータを変数に読み込む with open('save.json', 'r') as f: x = json.load(f) # ファイル名の変更、移動 import os os.rename('old', 'new')

Pythonでデータ出力を行なう方法

Pythonでデータをファイルに保存したり、出力表示する方法です。CGIなどのWebプログラムでは、ヘッダーを出力してからコンテンツ部分を出力する必要があります。注意点として、Pythonのprint()では改行も出力されるため、Content-Type: text/html\nの改行が一つになります。

# ファイル名の設定 FILE_NAME = 'file.txt' # 書き込むデータ lines = "" # 書き込むリスト li = ['a','b'] # ファイルを新規作成、上書きする with open(FILE_NAME,'w') as f: f.write(lines) # リストを1行に書き込む with open(FILE_NAME,'w') as f: f.writelines(li+"\n") # リストを行ごとに書き込む with open(FILE_NAME,'w') as f: f.write("\n".join(li)) # ファイルに追記する with open(FILE_NAME,'a') as f: f.write(lines) # 読み込んでから書き込む ファイルロック import fcntl with open(FILE_NAME,'r+') as f: try: fcntl.flock(f.fileno(), fcntl.LOCK_EX) for line in f: lines += line f.seek(0) f.write(lines) f.flush() f.truncate() except IOError: # 標準出力に出力する print('Hi') # cgiでブラウザにHTMLを出力 print("Content-Type: text/html\n") print('<b>Hi</b>') # cgiでブラウザにテキストを出力 print("Content-Type: text/plain\n") print('Hi')

Pythonの関数、クラスの作り方

開発を効率化するために、関数やクラスを作成できます。関数内では、変数はローカル変数となります。グローバル変数を利用したい場合は、global 変数名で使用できます。

またPythonでは、ラムダ式と呼ばれる無名関数を作成できます。関数名を定義せずに、関数の機能を式レベルで実装できるため、コーディングの効率化に役立ちます。ラムダ式を関数の引数として渡したり、配列や辞書の値として代入し、インデックスやキーで呼び出すなどが行えます。

# 関数を作成する def plus(a,b): return a + b # デフォルト値 def minus(a,b=1): return a - b # 引数の数を固定しない タプル型に def multi(*tup): r = 1 for v in tup: r = r * v return r r = multi(2,4,5) #40 # 引数の数を固定しない 辞書型に def get(key, **dic): return dic[key] if key in dic else None r = get('a', a=10,b=20) # ラムダ式 li = list(map(lambda x:x**2, range(5))) # ラムダ式 タプルに代入 fnA = ( lambda x:x+1, lambda x:x+2, lambda x:x+3 ) print(fnA[0](2)) # ラムダ式 辞書に代入 fnB = { "a": lambda x:x+1, "b": lambda x:x+2, "c": lambda x:x+3 } print(fnB['c'](2))

Pythonでは、オブジェクト指向のクラスも作成できます。privateなプロパティやメソッドなどのメンバは、先頭にアンダースコアを2つ付けて実装します。privateなプロパティは、継承されないためプロパティにアクセスするメソッドが必要となります。

# クラスを作成 class Base: # コンストラクタ def __init__(self,i=10): self.__v = i # プロパティ @property def v(self): return self.__v def set(self,i): self.__v = i def up(self): self.__v += 10 def down(self): self.__v -= 10 # クラスを継承 class Child(Base): def plus(self,p): self.set(self.v + p) # インスタンス作成 b = Base(50) b.up() print(b.v) # 派生クラスのインスタンスを作成 c = Child() c.plus(15) print(c.v)