構築環境
データ型
整数型 | |
浮動小数点型 | |
文字列型 | |
リスト型 | ・・・配列の様なもの |
辞書型 | ・・・連想配列の様なもの |
関数とメソッド
f = open(sys.argv[1]) | ・・・openは関数 |
x = f.read() | ・・・readはメソッド |
コメント
# | ・・・行コメント |
""" | ・・・複数行コメント |
3連クォート
シングルクォート | ・・・3つ並べて''' |
ダブルクォート | ・・・3つ並べて""" |
普通の書き方 str = "select"
str = str + " count(*)"
str = str + "from emp;"
3連クォートを使うと複数行に跨る長い文字列を簡単に書ける str = """
select
count(*)
from emp;
"""
文字列の特定の要素の取り出し
a = 'xyz' | ||
式 | 戻り値 | 説明 |
a[0] | x | 0番目 |
a[-1] | z | 末尾の1番目 |
'xyz'.upper()[1] | y | 関数やメソッドの戻り値の1番目 |
a[0:1] | x | 0番目から1番目の手前 |
a[:2] | xy | デフォルト(0番目)から2番目の手前 |
a[1:] | yz | 1番目からデフォルト(末尾)まで |
a[1:-1] | y | 1番目から末尾の手前 |
リスト
a = [1, 2, 3] | ||
b = ['abc', 'def' ,'ghi'] | ||
式 | 戻り値 | 説明 |
a[0] | 1 | 0番目の要素 |
a[-1] | 3 | 末尾の要素 |
a[-1]=4 | 末尾の要素を変更 | |
a.append(9) | 要素を追加 | |
b[1:2] | 'def' | 1番目から2番目の手前までの要素 |
値が辞書型 >>> die = [{"id": 0, "name": "Hero"},{"id": 1, "name": "Dunn"}] 要素の取得 >>> die[0] {'id': 0, 'name': 'Hero'} 0番目の要素のkey"name"のvalueを取得 >>> die[0]["name"] 'Hero' 全要素のkey"name"のvalueを取得 >>> for var in die: ... print var["name"] Hero Dunn 全要素に新たなkey:valueを追加(valueはリスト型) >>> for var in die: ... var["age"] = [] >>> print die [{'age': [], 'id': 0, 'name': 'Hero'}, {'age': [], 'id': 1, 'name': 'Dunn'}] 新たに追加したkey"age"に値をセット >>> die[0]["age"].append(20) >>> print die[0] {'age': [20], 'id': 0, 'name': 'Hero'} >>> print die[1]
タプル
リストは変更可能だが、タプルは変更不可
x = (1, 2, 3) | ||
式 | 戻り値 | 説明 |
x | (1, 2, 3) | |
a[0] | 1 | 0番目の要素が表示される |
x(0) | TypeError: 'tuple' object is not callable | 関数やメソッド(引数)と認識されエラーになる |
a[0]=4 | TypeError: 'tuple' object does not support item assignment | タプルは要素を変更出来ない |
インポート
import sys | ・・・モジュール単位でインポート |
from sys import argv | ・・・メソッド単位でインポート |
文の最後のコロン(:)とインデント
条件式の区切りを意味する
for i in range(len(y)):
if a == b:
pass
else
print 'a != b'
pythonには構文の終わりを示す記号がない。構文の区切りはインデントに積極的な意味を持たせることで示す
文の最後のカンマ(;)
改行を抑制する。特に指定しないと引数を表示したあと自動的に改行される
print line,
文の最後の円マーク(\)
条件式の継続文字
if (hoge >= '2000/04/01' and hoge <= '2001/'03/31' or \
hoge >= '2003/04/01' and hoge <= '2004/03/31') :
print 'bad range'
Perlのchomp
文字列の末尾の改行文字を削除する
if line and line[-1] == '\n':
line = line[:-1]
例外
全ての例外を一律で記述 try: スクリプト内容・・・ if value != 1: raise ValueError # 例外を発生させる exception Exception s: print s finally: f.close()
辞書型 {キー:値}
初期化 | die = {} |
値の取得 | die[キー] または die.get(キー) |
キーの追加 | die[キー]=値 |
キーの削除 | del die[キー] |
キーの一覧 | die.keys() |
値の一覧 | die.values() |
キーと値の一覧 | die.items() |
浮動小数点はキーに出来る | dic[12.5] = 12.5 |
タプルはキーに出来る |
dic[(1,2)] = 3 ※()は省略可 dic[1,2] = 3 ※ 後から変更不可のタプルはキーに指定できるが、 後から変更可能なリストはキーに指定できない |
keyのデータ型は統一する必要はない >>> die = {1:'apple', 'two':'orange'} >>> die[1] 'apple' >>> len(die) キーと値のペア数 2 >>> for k, v in die.items(): キーと値の一覧を表示 ... print k, v ... 1 apple two orange >>> for v in die.values(): 値の一覧を表示 ... print v ... apple orange 値の部分を辞書型に出来る >>> die = {'taro':{'age':18, 'high':170}, 'jiro':{'age':23, 'high':160}} >>> die['taro'] {'high': 170, 'age': 18}
テスト用ファイル
$ vim profiles.txt *太郎 年齢:18 身長:170 性格:おっとり 出身:北海道 *ハリー 年齢:20 出身:アイダホ 性格:神経質 髪型:よこわけ *ゆかり 性格:女 年齢:15 好物:おにぎり
# coding:utf-8
def prink(e):
"""日本語交じりのデータ内容を表示する。"""
print eval('"""%s"""' % str(e))
print help(prink)
"""ファイル全体を巨大な文字列の形で一気に読み込んでしまい、その後、
その文字列を操作する。
"""
f = open('profiles.txt')
x = f.read()
f.close()
dic = {}
person = ''
"""改行文字でファイル全体を分割して、行単位になったリストをlinesに入れる
"""
lines = x.split('\n')
for line in lines:
if line and line[0] == '*':
person = line[1:]
else:
"""splitの第2引数は分割回数。分割結果(リスト)がkvに格納される 例:['年齢', '18']
"""
kv = line.split(':', 1)
if len(kv) == 2:
if (person, kv[0]) not in dic:
dic[person, kv[0]] = []
"""辞書の中に、キー:person, kv[0]、値:kv[1]で格納される
"""
dic[person, kv[0]].append(kv[1])
for (p, attr) in sorted(dic.keys()):
prink('%sさんの%sは:%s' % (p, attr, dic[p, attr]))
"""ファイルにある各行をループによって1行ずつ読んでいきながら処理する
"""
f = open('profiles.txt')
line = f.readline()
while line:
スクリプト処理・・・
line = f.readline()
f.close()
実行結果
$ python people-dic.py ゆかりさんの好物は:['おにぎり'] ゆかりさんの年齢は:['15'] ゆかりさんの性格は:['女'] ハリーさんの出身は:['アイダホ'] ハリーさんの年齢は:['20'] ハリーさんの性格は:['神経質'] ハリーさんの髪型は:['よこわけ'] 太郎さんの出身は:['北海道'] 太郎さんの年齢は:['18'] 太郎さんの性格は:['おっとり'] 太郎さんの身長は:['170']
テスト用ファイル
$ vim category.list aaaa 000 bbbb 000 cccc 000 dddd 000 aaaa 111 cccc 222 bbbb 222 bbbb 333
summarize.py (キー項目でループさせるパターン)
"""
標準入力から1行づつ読み込む(sys.stdin)
1列目(kv[0])が変わるまで2列目(kv[1])をリストに格納(append)
1列目が変わったらリスト内容をカンマで結合(','.join)して出力。リストはクリア
"""
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
keyword = ''
category = []
for line in sys.stdin:
kv = line[:-1].split('\t', 1)
if keyword != kv[0] and keyword != '':
print keyword + '\t' + ','.join(category)
category = []
keyword = kv[0]
category.append(kv[1])
print keyword + '\t' + ','.join(category)
summarize2.py (辞書(key,[ ]) に格納させるパターン)
"""
標準入力から1行づつ読み込む(sys.stdin)
読み込んだ内容は辞書(1つのkeyに1つのリスト(複数value))に格納する ( setdefault(key, []).append(value) )
すべて読み終えたら、辞書を出力
set()の引数にリストを指定すると重複がなくなる ','.join(set(dic[key]))
"""
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
dic = {}
for line in sys.stdin:
kv = line[:-1].split('\t', 1)
dic.setdefault(kv[0], []).append(kv[1])
for key in dic.keys():
print key + '\t' + ','.join(dic[key])
実行結果
$ cat category.list | sort | python summarize.py > hoge aaaa 000,111 bbbb 000,222,333 cccc 000,222 dddd 000
関数
公式 ※ def文が呼び出されるまで関数名は定義されないので、関数の呼び出しはdef文の後にこなくてはいけない def 関数名(引数の並び・・・) ドキュメントが表示される print help(関数名) オプション引数 ※ 関数の呼び出し時、第2引数を省略するとデフォルト':'がセットされる def 関数名(引数1, 引数2=':'): 可変個の引数 ※ 引数はタプルとして扱われる。関数名(a, b, c)で呼び出された場合、len(引数1)は 3 になる def 関数名(*引数1)
$ vim test.py def testdef(*par): print len(par), par testdef('a', 'b', 'c') testdef('a', 'b', 'c', 'd') $ python test.py 3 ('a', 'b', 'c') 4 ('a', 'b', 'c', 'd') 辞書を使った呼び出し ※ 引数に**を付けると、関数側で引数を辞書として受け取ってくれる def f(**dic): print dic f(x=20, y='z', f=20.5) 結果 {'y': 'z', 'x': 20, 'f': 20.5}
モジュール
・ある機能を分離して別のファイルに整理したもの
・ファイル名が自動的にモジュール名になる
・他ファイルからのモジュールの呼び出し import モジュール名() モジュール名.関数名(引数・・・)
・特殊モジュール変数:__name__ 呼び出されたモジュールの__name__にモジュール名が自動設定される
・モジュールの最後に__main()関数を定義して、関数の呼び出し部分をその中に記載する
モジュールを直接実行すると、そのモジュールには'__main__'という名前が割り当てられる def __main(): dic = read_file('profiles.txt') disp_dic(dic) if __name__ == '__main__': __main() モジュールを直接実行するとTrue判定され__main関数が呼び出される
・モジュール変数 モジュールファイルのdef文やクラス文の外側に記載した変数。モジュール変数は外からもアクセスできる モジュール名.モジュール変数
クラスの要点
(1) | class クラス名 |
(2) | モジュール名はファイル名と同じになる |
(3) | モジュール名とクラス名は別々に出来る |
(4) | 1つのモジュール内に複数のクラスを定義出来る |
(5) | クラスの中に書いた関数をメソッドと呼ぶ |
(6) | メソッドが呼び出される際の第1引数にはインスタンスが渡される。慣習的に self が付けられる |
(7) | インスタンス変数は、この self の属性として設定する。 self.dic |
(8) | 特殊メソッド __init__() はインスタンスが生成された直後に呼び出され、インスタンス変数の初期化を行う |
(9) | __init__() の定義はオプションなので、定義しなくても問題ない |
(10) | インスタンス変数はメソッドに対して外から与える情報、かつ外へ伝える情報 |
テスト用ファイル
$ cat profiles.txt 前述と同様 |
$ cat profiles5.txt *太郎 年齢:20 身長:170 好物:パイン *次郎 年齢:10 出身:鳥取 性格:神経質 |
$ cat profiles6.txt *太郎 年齢:20 身長:170 性格:おっとり 出身:硫黄島 *次郎 年齢:10 性格:やさしい |
# coding:utf-8
version = '0.1' # モジュール変数
def prink(e):
"""日本語交じりのデータ内容を表示する。"""
print eval('"""%s"""' % str(e))
"""モジュールにクラスが1つの場合はモジュール名とクラス名を同じにするのが慣習
1モジュールに複数クラスを記述する場合はモジュール名とは違う名前をクラスに付ける"""
class people:
def __init__(self):
self.dic = {} # インスタンス変数の初期化
def add_item(self, person, key, value):
"""このメソッドは、辞書dic の(person, key) で示されるキー値に
valueを追加する。まだ1つも値がない場合には、空のリストを追加
してvalueが追加できることを保障する"""
""" dic = self.dic によりローカル変数 dic は インスタンス変数 self.dic を
指しているので、dic に更新した内容は self.dic にも反映される"""
dic = self.dic
if (person, key) not in dic:
dic[person, key] = []
dic[person, key].append(value)
def read(self, filename):
f = open(filename)
x = f.read()
f.close()
dic = self.dic
person = ''
lines = x.split('\n')
for line in lines:
if line and line[0] == '*':
person = line[1:]
else:
kv = line.split(':', 1)
if len(kv) == 2:
"""あるメソッドから同じクラスの別のメソッドを呼び出す。
引数の * について
・引数に * を付けるとメソッド内では引数をタプルとして受け取る
・可変個の引数をもつメソッドを定義する時に使用"""
self.add_item(person, *kv)
def write(self, filename):
"""filename引数で指定されたファイルに辞書dicの内容を書き出す
"""
g = open(filename, 'w')
dic = self.dic
person = ''
for (p, attr) in sorted(dic.keys()):
if person == '':
g.write('*%s\n' % p)
elif person != p:
g.write('\n*%s\n' % p)
person = p
g.write('%s:' % attr)
g.write(','.join(dic[p, attr]))
g.write('\n')
g.close()
def __str__(self):
"""オブジェクトを print() に渡した際は、特殊メソッドの __str__() が
呼ばれることになっている。ここでは辞書dic の内容を編集表示している。"""
dic = self.dic
s = ''
for (p, attr) in sorted(dic.keys()):
s += '%sさんの%sは: %s\n' % (p, attr, ','.join(dic[p, attr]))
return s
def _main():
"""インスタンス生成。クラス名を関数と見立てて呼び出す
p が返ってきた時点で __init__() の呼び出しは完了している"""
p = people()
p.read('profiles.txt') # メソッドは、インスタンス変数.メソッド名で呼び出す
print p # 自動的に__str__()が呼び出される
prink(p.__str__()) # 明示的に__str__()を呼び出す
p.add_item('ジャネット', '正体', 'サイボーグ')
p.write('profiles4.txt')
if __name__ == '__main__' : _main()
# coding:utf-8
from people import people, prink # from モジュール名 import クラス名、メソッド名
"""class 派生先クラス(派生元クラス)"""
class peoplex(people):
uniq_list = ['出身', '年齢', '身長'] # クラス変数
def __init__(self):
"""pythonの場合、派生元クラスの__init__()が暗黙的に呼び出される
仕組みはないので、必要に応じて明示的に呼び出す必要がある"""
people.__init__(self)
def add_item(self, person, key, value):
"""派生したクラス(peoplex)で派生元のクラス(people)のメソッドを上書き(オーバーライド)
peopleクラスとの違いは、クラス変数uniq_listに含まれる項目については重複した挿入を許さ
ないところ"""
dic = self.dic
if (person, key) not in dic:
dic[person, key] = []
"""メソッドからクラス変数にアクセスするには self.__class__.~の形で使う"""
if key in self.__class__.uniq_list:
if len(dic[person, key]) > 1:
raise ValueError # 意図的に例外を発生させる
if len(dic[person, key]) == 1:
if value == dic[person, key][0]:
"""同じ値が指定された場合はスキップ"""
pass
else:
"""別の値が設定された場合は例外を飛ばす"""
raise ValueError, \
"(person, key, value)=(%s,%s,%s)" % (person, key, value)
else: # len == 0
"""初めての値の場合はリストに挿入"""
dic[person, key].append(value)
else:
"""uniq_listにないキーの場合は普通に挿入"""
if value not in dic[person, key]:
dic[person, key].append(value)
def __str__(self):
"""オーバーライドのメソッド。peopleクラスとの違いは、人物名を一度だけ表示する"""
dic = self.dic
s = ''
person = ''
for (p, attr) in sorted(dic.keys()):
if person == '' or person != p:
s += '%sさんの情報:\n' % p
s += '\t%sは:%s\n' % (attr, ','.join(dic[p, attr]))
person = p
return s
def _main():
x = peoplex()
x.read('profiles5.txt')
x.read('profiles6.txt')
print x
prink(x.__str__())
if __name__ == '__main__' : _main()
実行結果
$ python people.py ゆかりさんの好物は: おにぎり ゆかりさんの年齢は: 15 ゆかりさんの性格は: 女 ハリーさんの出身は: アイダホ ハリーさんの年齢は: 20 ハリーさんの性格は: 神経質 ハリーさんの髪型は: よこわけ 太郎さんの出身は: 北海道 太郎さんの年齢は: 18 太郎さんの性格は: おっとり 太郎さんの身長は: 170 ゆかりさんの好物は: おにぎり ゆかりさんの年齢は: 15 ゆかりさんの性格は: 女 ハリーさんの出身は: アイダホ ハリーさんの年齢は: 20 ハリーさんの性格は: 神経質 ハリーさんの髪型は: よこわけ 太郎さんの出身は: 北海道 太郎さんの年齢は: 18 太郎さんの性格は: おっとり 太郎さんの身長は: 170 |
$ python peoplex0.py 太郎さんの情報: 出身は:硫黄島 好物は:パイン 年齢は:20 性格は:おっとり 身長は:170 次郎さんの情報: 出身は:鳥取 年齢は:10 性格は:神経質,やさしい 太郎さんの情報: 出身は:硫黄島 好物は:パイン 年齢は:20 性格は:おっとり 身長は:170 次郎さんの情報: 出身は:鳥取 年齢は:10 性格は:神経質,やさしい |
参考先