Pythonメモ 
top

型の比較

import types
a = 'string'
if type(a) == types.StringType:
  print 'yes'
else:
  print 'no'

type()で型が取得できる。typesモジュールにはシステム定義型の値が用意されている。

文字列型

unicode型あるいはstr型であるかどうかは、basestringを使うと判定できる。

a = 'hello'
b = 150
c = u'漢字'
isinstance(a, basestring) --> True
isinstance(b, basestring) --> False
isinstance(c, basestring) --> True

basestringは、ビルトイン関数として定義されているが、呼び出したり、インスタンス化することができない。

ジェネレーター関数(generator function), yield文

generator functionを定義するときに使う。逆に関数を定義するときにyield文を使うと、その関数はgenerator functionとなる。

generator functionを呼び出すとgeneratorと呼ばれるiteratorが返される(実際の型はgenerator型)。以降の操作は、このgeneratorのメソッドを呼び出して行う。コードの実行は、yield文が現れるまで行われる。

generator functionの中身はgeneratorのnext()メソッドを呼ばれたとき実行される。つまりgenerator functionが呼ばれた時点では中身は実行されない。

yieldが呼ばれたところで、実行が止まった形になる。遅延評価の形になる。generator functionのローカル変数はその間も保たれる。

ジェネレーター関数が使われるケース

呼び出す度にフィボナッチ数を1つずつ返すような場合。

ファイルからひとかたまりのデータを読み込み、その処理が終わったらまた次のひとかたまりのデータを読み込み処理したい場合、理想的にはデータの読み込みと、そのデータの処理を切り離して書けると嬉しい。こんな場合にジェネレーター関数が役に立つ。

8進数/16進数からの変換

int('10', 8)  8
int('0a', 16)  10

リスト操作

リストの要素をinsert

0番目の要素の前に’new’を入れる

mylist = ['a','b','c']
mylist.insert(0, 'new')

リストの要素を消す

del a[0]
del a[2:4]

配列を初期化する

ary = 38 * [None]

なんか効率悪そう。

リストの各要素に対し一括処理を行う

map()ビルトイン関数を使う。

numbers = [1,2,3,4,5]
map(str, numbers)
['1','2','3','4','5']

map()は、str(x)をnumbersの各要素をxとして実行し結果をリストとして生成する。

ちょっと変わった処理をしたいなら、str()の代わりにラムダ関数を使う。

numbers = [1,2,3,4,5]
map(lambda x:x+1, numbers)
numbers = [2,3,4,5,6]

実行ユーザーの取得

uidを取得するだけなら、

import os
print os.getuid()

ユーザー名を取得するなら

import pwd, os
print pwd.getpwuid(os.getuid())[0]

辞書の操作

便利なupdateメソッド

a = {1:'A', 2:'B'}
b = {2:'C', 3:'D'}
a.update(b)

a -> {1:'A', 2:'C', 3:'D'}

os.system()で使用されるPATHを変更する

os.system()は環境変数を参照するので、環境変数PATHを変更すれば良い。

import os
os.system('echo $PATH')
os.environ['PATH'] = ''
os.sytem('echo $PATH')

Unicode/日本語

str = unicode('EUC文字列', 'japanese.euc_jp')
for c in str:
  print type(c), c.encode('japanese.euc_jp')

この例では、ソースコードをEUCで書いたり、外部からのデータをEUC-JPで渡したりする場合を想定している。

変数strはunicode型の文字列で、unicode()を使って生成している。 unicode型の文字列では、漢字1文字も1文字として扱われる。出力時には、encode()メソッドを使う。ここではEUC-JPに変換して出力している。

% python gaku2.py
<type 'unicode'> E
<type 'unicode'> U
<type 'unicode'> C
<type 'unicode'> 文
<type 'unicode'> 字
<type 'unicode'> 列

unicode型だとはいっても、UTF-8なわけではない。unicode型をUTF-8で出力するには、str.encode(‘utf-8’)としなければならない。

try〜finally

try:
  statement A
finally:
  statement X

statement Xは、tryの中で例外が発生した場合も、しなかった場合も実行される。 実行のタイミングは、例外がない場合はtry節処理の直後、例外が発生した場合は、 例外発生直後で、finally節を実行した後、もとの例外が再度発生させられる。

スタックの表示

import traceback

def foo(a):
  print traceback.print_stack()

で一応表示できる。詳細は、Python.orgのtracebackモジュールを参照。

メソッド呼び出し

Pythonメソッド呼び出し

時間関連

現在時刻を取得する

time.time()
-> 1037158902.56

実数で返ってくるので、丸めると良い。

now = int(time.time())

年月日や時刻を特定の形式で表示したい

time.strftime("%T", time.localtime(time.time()))

時刻を表す値を生成したい

int(time.mktime((year, month, day, 0, 0, 0, 0, 0, -1)))

mktimeは、9つの要素を持つtupleを引数に取る。デイライトセービングは無視してよければ最後の要素は-1。やはり値は実数なので丸めるのもよし。

<

文字列

文字列の置換 string.replace()を使う。

//“を”/“にする。

import string
str = "/hello/world//from/Japan/"
newstr = string.replace(str, '//', '/')

文字列の連結

a = "hello"
b = "world"
c = a + " " + b

cは”hello world”となる。

文字列のフォーマット

first ='Gaku'
last = 'Ueda'
str = 'My name is %(first)s %(last)s.' % vars()

vars()は、現在のシンボルテーブルをdictionaryとして返す。 カッコ内の名称と変数名が関連づけられ、値割り当てができる。

クラス内であれば、vars(self)とすれば、メンバ参照ができる。

class abc:
  def __init__(self):
    self.member1 = "HELLO"
    self.member2 = "WORLD"
  def doSomething(self):
    print "%(member1)s and %(member2)s" % vars(self)

行末の改行を落とす

import string
line = string.rstrip(line)

文字コードの取得 a = "hello" b = ord(a[0]) 先頭の文字は、文字列a[0]でアクセスできる。組み込み関数ord()で文字コードに変換できる。 逆に文字コードから文字を得るにはchr()を使う。 chr(b + 1)

ファイル

Windowsでファイルを一気に読み込む。

fp = open(filename, 'rb')
data = fp.read()

‘r’の代わりに’rb’としていしないとWindowsでは、バイナリファイルを一気に読み込むことはできない。UNIXの場合には特に必要はない。

ファイルの末尾から128バイト読み込む

fp = open(filename, 'r')
fp.seek(-128, 2)
bytes = fp.read(128)

seekの第2引数の2は、ファイルの末尾をオフセットとする。-128でそこから128バイト戻す。

リネーム: os.rename()を使う

import os
os.rename(newname, oldname)

存在チェック: os.access()

import os
os.access('/etc/rc', os.F_OK)

標準入力から1行ずつ読み込む

import sys
while 1:
  line = sys.stdin.readline()
  if not line:
    break
  sys.stdout.write(line)

lineには改行文字も含まれる。

特定のパターンのファイル名の取得

import glob
files = glob.glob('dat/2003*')
for f in files:
  print f

とすると、filesは、[‘dat/20030811’, ‘dat/2003/0812’]といったような結果となる。

ファイルへの書き込み

f = open('filename', 'w')
f.write("hello\n")
f.close()

複数のプロセスから1つのファイルに書き込む

import fcntl
import sys, time

while 1:
  file = open('/tmp/locktest', 'a')
  fcntl.lockf(file.fileno(), fcntl.LOCK_EX)
  file.write("from %s" % sys.argv[1])
  time.sleep(1)
  fcntl.lockf(file.fileno(), fcntl.LOCK_UN)
  file.close()

演算

整数切り上げ

import math

f = 3.1415
n = int(math.ceil(f))

mathモジュールのceilメソッドで切り上げができる。結果はfloatのままなので、int()で整数化する。

os.system()のPATHの変更

os.environ['PATH'] = "/sbin:/usr/bin"
os.sytem('ifconfig')

main()の書き方

def main():
  ...
  ...

if __name__ == '__main__':
  main()