Pythonを学ぶ その6
正規表現
文字列の頭が数字?
re.match('\d+',text)
re.serch('^\d+',text)
re.match()
は先頭からマッチするものを
re.serch()
はどこでもマッチするものを確認する
マッチしなければNone
が返される
マッチしていたらマッチ型が返される
マッチしているものに対して行える操作がある
m.group()
m.start()
m.end()
m.span()
...
こういう関数はNoneオブジェクトに対して使用するとエラーが返されるので、一般的に
if m: マッチした時の処理 else: ...
という風に
マッチする文字列の部分抽出
数値を抜き出す
re.match(~~~~~,text)
~~~の部分でどういう風にデータを構造化するか、そして()で抽出する要素を指定する
findall()
で全部取得
ちなみに少し気になったけど、リストでなく配列という言葉を使っている箇所がある。なぜ?
コンパイル
regex = re.compile(~~)
とすることで
regex.match(text)
というように、正規表現を書かずに済む
演習
import re i = re.findall('([A-z]+)\W', 'I have 2 pens.') print(i)
日本語を扱う
文字を表現するにはバイナリを文字コードに従って変換する必要がある。 文字を扱う場合はファイル内で使用する文字コードは統一すること。
使うときは
# config:utf-8
日本語を扱うには、unicode文字列型として使う。 文字列の先頭にuをつけてあげればいい
文字列への変換text.encode('shift-jis')
unicode文字列への変換text.decode('shift-jis')
pythonで日本語のテキストファイルの読み書き
import codecs f = codecs.open('utf-8.txt','r','utf-8') for line in f: print(type(line)) print(line) f.close()
取得してくるとunicode文字列型に成ってる
演習1
import math def tentwo(x): x = float(x) i = int(math.log(x,2)) print(i) if(i == 0): return 0 else: y = [] print(type(y)) while(x != 0): if((x < pow(2,i)) == True): print('0notoki'+ str(x) + '.' + str(pow(2,i)) ) y.append("0") x = x i = i - 1 print(y) else: print(str(x) + '.' + str(pow(2,i)) ) y.append("1") x = x - pow(2,i) i = i - 1 print(y) y = "".join(y) return int(y) #print('enter an intger') #x = raw_input() x = 35 print('x =' + str(tentwo(x)))
なぜかjoinがうまく使えなくてコマった
演習3
# coding: utf-8 text = u'今日はいい天気ですね。おはようございます。ハロー' n = text.split(u'。') for line in n: print(line)
リストとしてやるとダメなんやね
つまり
print(n)
でやると、ちゃんと出てこない
演習4
import sys import codecs name = sys.argv[1] fcodec = sys.argv[2] wr = sys.argv[3] f_in = codecs.open(name,'r',fcodec) f_out = codecs.open(name+'.'+fcodec+'.txt','w',wr) for line in f_in: f_out.write(line) f_in.close() f_out.close()
sys.argv
がファイル名から格納されているのを忘れてた
今日はここまで
Pythonを学ぶ その5_2
演習3
import math f = open('ex12.txt','r') g = open('ex10.txt','w') text = f.readlines() print(text) j = int(math.log10(len(text)))+1 i = 0 for lines in text: g.write(str(i).zfill(j)+lines) print(lines) i += 1 f.close() g.close()
演習5
略
pickle、通常のファイル操作と何が違うのかわかんねー バイナリを経由しているのがポイントなんだろうが、だからどうしたって感じだ
Pythonそれ自体を保存するってことなのかもしれない? 辞書を辞書として、とか
Pythonを学ぶ その5
テキストを生成する方法
text1 = 'hello python' text2 = '''hello world python''' print('hello' + 'world') print('hello + str(5)')
文字列にテキストや数字を埋め込む
>>> 'hello {}{}'.format('python',5) 'hello python5' >>> 'hello {} {}'.format('python', 5) 'hello python 5' >>> print('5'.zfill(6)) 000005 >>> print(str(101).zfill(5)) 00101 >>> print('hello {0:05d} world'.format(5)) hello 00005 world >>> print('escape sample1 \.') escape sample1 \. >>> print('escape sample1 \'.') escape sample1 '. >>> print('escape sample1 \a.') escape sample1 . >>> print('escape sample1 \\.') escape sample1 \.
テキストを加工する
文字の取得
リストと同じように
マイナスにすると後ろから数えた文字列を
[x:y]
でx番目より後ろ、y番目より前を取得
>>> print(text[4]) o >>> print(text[100]) Traceback (most recent call last): File "<stdin>", line 1, in <module> IndexError: string index out of range >>> print(text[-4]) t >>> print(text[6:]) world python >>> print(text[:11]) hello world >>> print(text[:]) hello world python >>> print(text[6:11]) world
文字列.replace(x,y)
xをyに置き換え
検索1:存在の確認 検索2:位置の確認
>>> 'wor' in text True >>> 'heli' in text False >>> text.find('wor') 6 >>> text.find('heli') -1 >>> text.find('o') 4
find
はマッチしたものの一番左にあるものの位置を返す
rfind
は右
strip
split
text = '''1,taro,35,male 2,jiro,29,male 3,hanako,23,female''' print('thank n you') for line in text.split('\n'): elems = line.split(',') print('{} {}'.format(elems[1].strip(),elems[2].strip()))
特定の文字列で結合
>>> p = ['1','taro','36','male'] >>> ','.join(p) '1,taro,36,male' >>> p ['1', 'taro', '36', 'male']
ファイル処理
プログラムがどのようにファイルを扱うかは、OSの仕組みに基づいているため多くのプログラミング言語でさほど変わりません
- ファイルを指定
- ファイルをオープン
- 読み書き
- ファイルをクローズ
読み書きの処理
テキストファイルは行ごとに処理 バイナリファイルは先頭から何バイト目かを指定して処理
f = open('text.txt','r') print(type(f)) for line in f: print('hello' + line) f.close()
print
の改行をなくすには後ろに,
丸ごと読み込み、文字列として取得するread
f = open('text.txt','r') text = f.read() print(text) lines = text.split('\n') print(lines) f.close()
ファイルに書き込み(上書き)
f = open('text.txt','w') f.write('123') f.write('456') f.close()
追記する必要ある時は、モードをa
にする
ディスクへの書き込みを強制的に行いたい場合(closeのタイミングで必ず書き込まれるが途中でやりたいのなら)flush()
関数
Pickle
Pythonのデータをファイルに保存し、読み取って復元する
import pickle a = {'hello':1,'world':[1,2,3]} f1 = open('test.dump','wb') pickle.dump(a,f1) f1.close() f2 = open('test.dump','rb') b = pickle.load(f2) f2.close() print(b)
そういえば、
split
関数は、text.split()
みたいに、textを対象にすることができる。
こういう形で関数の前に文字列.
をつけられるようにするにはどうすれば良いのだ?
普通に引数として渡せば良いのだけど。
今日はここまで
Pythonを学ぶ その4
知っていると便利な型
タプル
タプルもリストと似ていて、ひとつの型のなかに複数のデータを格納します。ただ、その目的は異なっていて、「決まった数の複数のデータがひとつの意味を持つもの」にタプルは使われます。
会員情報>氏名、生年月日、住所
タプルの作成はタプルの要素となる値を()で囲むことで作成できます。
a = ('taro','1986','tokyo')
参照するにはa[0]
要素を一気に取得する(b,c,d) = a
リストと異なり、一度作成されたオブジェクトを変更することはできません
セット
集合という概念を実現するための型 - 順序 - 重複 がない
set()
関数:空のセットのオブジェクトの作成
>>>a = set() >>>b = set([1,3,5,7]) >>>print(b) set([1,3,5,7]) >>>b.add(2) >>>b.remove(5) >>>print(b) set([1,2,3,7])
要素の存在を確認する
データをリストにするlist(a)
>>>3 in a True
ハッシュ
ある要素を指定するとハッシュ値を返す関数のこと 集合はハッシュが使われている(?)
辞書型(連想配列、マップ)
重複が許されないKeyとそのValueが対応付けられたデータ型。 セットにおけるハッシュ値にValueを対応しているもの
辞書オブジェクトの生成にはdict()
関数か、{key:value}
を使う
keyの取得にはc[]
keyの存在を確認するのはセットと同じ
has_key()
,get()
関数を使ってアクセスすることもできる
keys()
キー一覧
values()
値一覧
>>> a = dict() >>> type(a) <type 'dict'> >>> b = {} >>> type(b) <type 'dict'> >>> c = {"apple":"red","lemon":"yellow"} >>> type(c) <type 'dict'> >>> c['apple'] 'red' >>> c['apple'] = "green" >>> c['apple'] 'green' >>> 'apple' in c True >>> c.has_key('apple') True >>> c.get('apple') 'green'
関数型
関数も型の一種です
>>> def test(): ... return1 File "<stdin>", line 2 return1 ^ IndentationError: expected an indented block >>> def test(): ... return 1 ... >>> type(test) <type 'function'> >>> test2 = test >>> type(test2) <type 'function'>
インデント必要なので注意
関数を引数にすることができるってこと?(関数を引数に持つ関数を高階関数と呼ぶ)
def fun1(fun,x): fun(x) def fun2(x): print('fun2:' + str(x)) fun1(fun2,5)
クロージャ
テンプレートとなる関数からカスタム関数を生成する?
ef adder(x): def fun(y): return x + y return fun adder5 = adder(5) print(adder5(10)) adder7 = adder(7) print(adder7(10))
adderの引数を内部で作成する関数で利用している
面白いw 数学やってるみたいだ。。。
演習1
リストから重複を取り除く関数をセットを使って作成してください
print("enter the list as follows: x1,x2,...") x = raw_input() # x = "1,2,3,3,4" x = x.split(',') print(x) print(type(x)) def nodupli(x): y = set() for a in x: y.add(a) z = [] for a in y: z.append(a) return z print(nodupli(x))
ああ、set(x)
でよかったんだ
演習2
標準入力を使って生徒の成績を管理するツールを作ってください。"save 生徒名 点数"とするとその生徒の点数を保存します。"get 生徒名"とするとその生徒の点数を表示します。生徒が登録されていない場合は"Error"と出力させて処理を継続させます(※ 終了はCtrl-Dなどで強制終了してかまいません)。
sdata = {'sai':'100','hikaru':'10','akari':'20'} while(True): print('''to save student's score: enter 'save student_name score', to get student's score: enter 'get student_name' ''') x = raw_input() x = x.split() print(x) if(x[0] == 'get'): print(x[1]) print(sdata[x[1]]) elif(x[0] == 'save'): sdata[x[1]] = x[2] print(sdata) elif(x[0] == 'quit'): break else: print('error')
アラがあるけど、とりあえずできた。
演習3
英語の文章の単語出現数をカウントするプログラムを書いてください。たとえば'hello python hello world'というテキストを与えると{'hello':2, 'python':1, 'world':1} が返ってきます。なお、当然ながら辞書オブジェクト内のキーの順序は問いません。
#x = "hello python hello world" print("write a sentence") sentence = raw_input() x = sentence.split() print(x) lenx = len(x) print(lenx) y = dict() i = 0 j = 0 while((i < lenx) == True): # key wo kakunousuru y[x[i]] = 1 print(y) i += 1 #value wo ireru #kasanattara plus 1suru i = 0 while((i < lenx) == True): j = i + 1 while((j < lenx) == True): if(x[i] == x[j]): y[x[i]] += 1 j += 1 i += 1 print(y)
Keyを入れるのと、Valueを入れるので別の操作にしてみた
解答はスマートだなぁ。。。。愚直にやりすぎてる。。。 それと、もっと関数を定義してやるべき。 あと、条件分岐もC風にやってしまったけどはいけない。 今日はここまで
Pythonを学ぶ その3
関数とモジュール
関数でしか実現できないこと
プログラムの外と内をつなぐためには関数が必須
関数の宣言と使いかた
入力と出力 入力がないなら関数の宣言の引数をなくし、出力が不要な場合はreturnをなくせば良い
def my_func1(): return 0 def my_func2(x): x=x*-1
引数は複数指定できるが、returnは一度しか実行されない(returnされた後の処理は一切無視される
global宣言
関数内の処理の実装は、関数の定義の中で完結すべきです。その関数を実行することで、その関数の外の変数などの値を変更すべきではありません。
だが、それも時と場合による
x = 5 def add(): x += 1 print(x) add() print(x)
これは、関数の中で変数x
に値が与えられる前に参照したとされ、エラーがでる。
従ってglobal変数を導入して、関数の外で定義された関数を使う
x = 5 def add(): global x x += 1
とはいえ、
関数などを動かすことで「期待される範囲を超えた外の世界に影響が及ぶ」ことを「副作用」と言います。この副作用を減らすことが綺麗なコードを書くコツ
とのこと。あるいは、副作用のないコードが綺麗なコードと言われるのかもしれない。
モジュール
プログラムを特定の処理ごとにファイルを分ける 分けられた各ファイルをモジュールという
モジュールの利用
モジュールを利用するにはimport モジュール名
モジュール内の関数を呼び出すにはモジュール名.関数()
import math floor = math.floor floor(5.5)
という使い方もできるらしい。(関数を定義することとは違う?)
モジュール名なしで呼び出す
#from モジュール名 import 関数名 >>>from math import floor >>>floor(5.5) 5.0
モジュールの作成
.pyのファイルにコードを書けば良い
モジュールを書くにあたって注意すべきこと - 再利用可能か - 似た処理のみをまとめているか
モジュールとして使われる時には実行しない処理を書くこともできる その時は、
if(__name__ == '__main__'): 処理
と書けば良い。
演習1
絶対値を返す関数my_abs()
を作る
def my_abs(x): if(x < 0): x = x * -1 return x
演習2
引数で与えた数だけフィナボッチ数を配列で返す関数my_fiboを作る
def my_fibo(x): i = 1 y = [] while(i != x): if(i == 1): y.append(1) i += 1 elif(i == 2): y.append(0 + y[0]) i += 1 else: y.append(y[i-3]+y[i-2]) i += 1 return y print(my_fibo(x))
演習3
演習1、2の関数をモジュール化して別ファイルから使う できた
ユーザーからプログラムへの入力をする方法
コマンドライン引数
プログラムの起動時に指定する引数
使いかた
$ python file.py コマンドライン引数
とすることで、プログラムに引数を渡せる
sysモジュールをインポートすると
sys.argv
に['file.py',コマンドライン引数]
とリストとして格納される
引数のn番目はリストのn-1番目に格納される(複数の引数を指定できる
import sys # 誤った入寮地の場合はメッセージとともにプログラム中断(無言でプログラムを終わらせないようにしたほうが良い if(len(sys.argv)<2): #最初にチェックしてしまおう print('usage: student.py student_name') exit() student = sys.argv[1] score_sheet = get_score_sheet(student) print(score_sheet)
標準入力
プログラムの起動後に入力値を与える
raw_input()
関数は、実行されるとユーザーの入力を待つ
ユーザーがテキストを入力してenterを打つと、raw_input()
関数は入力されたテキストを返す
sysモジュールのreadline()関数も同じように使えるけど、Enterも取得されます。
インタラクティブなプログラムの書き方
そもそも、「インタラクティブなプログラム」とは 1. ユーザーからの入力をアプリケーションが待つ 2. それに応じてアプリケーションが何らかの処理をする 3. 1に戻る
結局while(True)
でループさせてやれば良い
exec
exec
は文字列として与えられたpythonのプログラムを実行する
演習1
コマンドライン引数で与えた二つの整数を足したものを表示するプログラムを作ってください。引数が二つ以外の場合はエラー表示して処理を中断させてください
import sys if(len(sys.argv) < 3): print('usage: student.py student_name student_number') exit() print(sys.argv) print(int(sys.argv[1])+int(sys.argv[2]))
< 3
はまずかったな
演習2
標準入力で受け取った文字列をecho: 文字列
として表示するプログラムを作る。exitと入力されたら終わる
while(True): print("give me text") text = raw_input() if(text == 'exit'): break print("echo: " + text)
give me text oisiiii echo: oisiiii give me text aaaaaa echo: aaaaaa give me text exit
演習3
標準入力で受け取ったPythonのプログラムを実行するプログラム。
while(True): print('give me python') python = raw_input() if(python == 'exit'): break exec(python)
give me python 9+9 give me python a = 3 + 3 give me python print(a) 6 give me python exit
今日はここまで
Pythonを学ぶ その2
リストの操作
リストには違う型のデータが入る
c = [1,"2",False]
要素の指定は、
リスト名[要素の番号]
(番号は0から数えることに注意)
リストにデータを加える
末尾への追加append()
c.append(4)
途中に追加
c.insert(x,y) #リストcに対してx番目にyを追加する
削除
c.remove(x)
リスト長の取得
len(c)
配列との比較
配列:メモリ上に要素を連番で格納する リスト:バラバラに用意された要素を順序付ける
ので、配列は要素の間にデータを追加することができない また、配列は配列の長さを変えられない
演習
1.文字列' hello 'から前後の空白をすべて取り除く
' hello '.strip()
ちょっといじってたらstrip()
で取り除いてくれない場合があることに気がついた
>>> a= 'sdfafoirewkkkkkppppp' >>> a.strip('s') 'dfafoirewkkkkkppppp' >>> a.strip('d') 'sdfafoirewkkkkkppppp' >>> a.strip('ppp') 'sdfafoirewkkkkk' >>> a.strip('kk') 'sdfafoirewkkkkkppppp'
strip()
は前後の文字しか消してくれないっぽい
string.strip(s[, chars])(原文) 文字列の先頭と末尾から文字を取り除いたコピーを生成して返します。 chars を指定しない場合や None にした場合、先頭と末尾の空白を取り除きます。 chars を None 以外に指定する場合、 chars は文字列でなければなりません。
バージョン 2.2.3 で変更: chars パラメタを追加しました。初期の 2.2 バージョンでは、 chars パラメータを渡せませんでした。 公式ドキュメントより
条件分岐
if(cond A): ----- elif(cond B):#条件AがFalseで条件BがTrueのとき ----- elif(cond C):#条件A、BがともにFalseのとき ----- else:#すべての条件がFalseのとき -----
インデントでコードブロックを作る。
x = -3 if(x>0): print('+') elif(x==0): print('0') else: print('-')
コードブロック
ifなどの制御構造がどの処理をカバーしているかを示すための表現
Cだと{}
で表現していて、プログラムとしてインデントする必要はなかった
処理1 if(A): 処理2 処理3 else: 処理4 処理5
処理5はelseの制御下にはない!
コードブロックの入れ子(ネスト)もできるよ
ループ処理
for
グループにある要素すべてを処理する
集合の一つを取り出してiに格納し、それを処理する
a = [1,2,3,4] for i in a: print(i)
俺の知ってるforと違う! ポイントは集合から取り出してiに格納するってとこ。 iを1-5まで動かしてa[i]をなんとか。。。。っていう形とは違うね
while
ループを何周すればいいかわからない処理
二進数の桁数を求めるプログラム
x =23 i=1 while(2**i<x): i += 1 print(i)
break, continue
y = [1,3,5,5,7,9,10,13,15] has_even = False for i in y: print(i) if(i%2 == 0): has_even = True break print("y has even:" + str(has_even))
試しに
y = [1,3,5,5,7,9,10,13,15] has_even = False for i in y: print(i) if(i%2 == 0): has_even = True break print("y has even:" + str(has_even))
とやってみたら、ちゃんと
1
で止まった。コードブロックすごい
continue
は特定の条件の時のみ処理するときに使う
演習1
[[1,5,3],[2,6,4]]
はリストにリストが入っています。内側のリストの最大値をそれぞれ求めるプログラムを書いてください
z = [[1,5,3],[2,6,4]] for i in z: print(max(i))
リストの最大値を求める関数を使ってみたけど、使わなかったとしたら
for i in z: maximum = i[0] for j in i: if(j > maximum): maximum = j print(maximum)
リストの中のリストの要素を指定するには
list[外側の要素番号][内側の要素番号]
z[1][2]
は3
演習2
1から100までの整数で - 3の倍数の時はFizz - 5の倍数の時はBuzz - 3の倍数でもあり5の倍数でもある時はFizzBuzz と表示するプログラムを書いてください
for i in range(1,100): if (i%3 == 0 and i%5== 0): print('FizzBuzz') elif(i%3 == 0): print('Fizz') elif(i%5 == 0): print('Buzz') else: print(i)
今日はここまで
Pythonを学ぶ その1
今日からPythonを学んでいくことにしました。 テキスト(?)はPythonで学ぶ基礎からのプログラミング入門
プログラミング自体は大学の講義などで触ったことはあります(C、perl)が、もうほとんど忘れてしまっているし、何かを作れるようなレベルではありません。
型と処理の結びつき
型と処理は密接に結びついていて、型にはそれぞれの処理がある
Cとの違い Cは変数と型が結びついている。変数にも型があって、変数の型と代入する値の型は同じじゃなくちゃいけない。 Pythonの変数はどのような型でも入れることができる! でもあまり変数を使い回すことは避けたほうが良い
型の種類
- 数値
- 文字列
- Bool
- リスト
数値型の処理
演算子
+
-
*
/
%
剰余**
べき乗
代入演算子
演算子の後ろに=
をつける
すなわちM = M + N
をM += N
とかける
(インクリメント/デクリメントはないよ)
演習1 図形の面積
- 変数に領域a, b, cの値をそれぞれ変数に代入してから、その面積の合計値を求める
a = 3 * 5 b = 4 * 3 c = 1 * 7 x = a + b + c print(x)
- 変数を使わないで領域a, b, cの合計の面積を求める
x2 = 3 * 5 + 4 * 3 + 1 * 7 print(x2)
演習2
1.文字列123
を整数の123に変換する
int(`123`)
2.文字列123.4
を少数の123.4に変換する
float(`123.4`)
ふむ、こうしてさがせばいいんだね。
int()
,float()
はこれで良いのか迷った。
というのも、この関数に入れる値は、数値型でないといけないのでは?と思ったから。問題になるのは、数値型にならない値の場合であって、型としては数値型でなくてもかまわない
文字列型
文字列は``
で囲む
+
や*
が使える
文字列をコードで作成するやり方
- シングルクオーテーションで囲む
- ダブルクオーテーションで囲む(変わりはないけど、シングルを文字列として扱いたいならダブルで囲めば良い。ただし
¥`
でも使える) - トリプルクオーテーション(見たままにテキストとして表示。コメントアウトとしての使用が主?)
文字列の操作
演算子の利用
>>>a = 'hello' >>>a += 'python' >>>print(a) 'hellopython'
str()
:文字列でない型を文字列型にする
文字列から関数を呼び出す
文字列.関数()
で文字列に対する操作をする
(文字列を格納した変数に対して変数.関数()
も同じ)
どゆこと?
例えば
>>> a = 'hello python' >>> a.find('py') 6
ここではa
は文字列を格納した変数
find()
は入力された値が前から何番目にあるか示す関数
やっとpythonのコードに~.~()という形式のものが多い理由がわかった
Cだと、find(a, py)
みたいにしてたよね
Bool型
真偽値のこと。True/False
- ==
- !=
- <>
- not A
- A and B
- A or B
リスト
配列?
results = [68,81,49] average = sum(results)/len(results) print(average)
変数を毎度作らなくて良いし、平均もデータの数によらず定義できている
今日はここまで