はてブロ@ama_ch

https://twitter.com/ama_ch

今日のPython

breakとcontinue

p.84

>>> for item in range(10):
...     if item == 5: continue
...     if item == 8: break
...     print item,
... 
0 1 2 3 4 6 7

while文

whileの条件はbool型(真or偽)で判定される。
p.86

>>> n = 0
>>> while n < 10:
...     print n,
...     n += 1
... 
0 1 2 3 4 5 6 7 8 9
九九の表を出力

よくやるよね。

>>> a = 1
>>> b = 1
>>> while a < 10:
...     while b < 10:
...             print a * b,
...             b += 1
...     print ""
...     a += 1
... 
1 2 3 4 5 6 7 8 9 







あれ、できない>< 
この改行は一体・・・


あ、わかった

>>> a = 1
>>> b = 1
>>> while a < 10:
...     while b < 10:
...             print a * b,
...             b += 1
...     print ""
...     a += 1
...     b = 1    #これ忘れてた
... 
1 2 3 4 5 6 7 8 9 
2 4 6 8 10 12 14 16 18 
3 6 9 12 15 18 21 24 27 
4 8 12 16 20 24 28 32 36 
5 10 15 20 25 30 35 40 45 
6 12 18 24 30 36 42 48 54 
7 14 21 28 35 42 49 56 63 
8 16 24 32 40 48 56 64 72 
9 18 27 36 45 54 63 72 81

for文と違うから、段が変わったら(aをインクリメントしたら)bの値をセットし直さないといけないんだった。初歩ミスすぎる><
表示桁数の調整がわからないからズレまくりだ


for文で書くとこう

>>> for a in range(1, 10):
...     for b in range(1, 10):
...             print a * b,
...     print ""
... 
1 2 3 4 5 6 7 8 9 
2 4 6 8 10 12 14 16 18 
3 6 9 12 15 18 21 24 27 
4 8 12 16 20 24 28 32 36 
5 10 15 20 25 30 35 40 45 
6 12 18 24 30 36 42 48 54 
7 14 21 28 35 42 49 56 63 
8 16 24 32 40 48 56 64 72 
9 18 27 36 45 54 63 72 81 

こっちの方がエレガントですね!

do〜while文がないので

Cのdo〜while文を使って0〜9を表示するとこんな感じ。

int main(void) {
  int n = 0;

  do {
    printf("%d ", n++);
  } while (n < 10);
  printf("\n");

  return 0;
}


Pythonではdo〜while文がないので、while文(無限ループ)とbreakを組み合わせて書く。
p.87

>>> n = 0
>>> while True:   #無限ループ
...     print n,
...     n += 1
...     if n == 10:
...             break
... 
0 1 2 3 4 5 6 7 8 9

関数

関数を作る

p.92 文字列を表示する関数を定義する

>>> def oppy():
...     print"Oppy(oppai)!!"
... 
>>> oppy()
Oppy(oppai)!!

def 関数名(引数):
[tab] 処理内容
て感じ。


引数の型を指定できないことに注意!
p.93

# 引数の回数だけ文字列を表示する
>>> def greeting(hello, python):
...     print "Hello " * hello,
...     print "Python!! " * python,
... 
>>> greeting(3,2)
Hello Hello Hello  Python!! Python!! 
# 引数で与えた文字列を指定した回数表示する
>>> def functest(str, int):
...     print str * int
... 
>>> functest("こんにちは! ", 5)
こんにちは! こんにちは! こんにちは! こんにちは! こんにちは!

こんな風に同時に受け取る引数の型が違う場合、関数の定義を読んだだけじゃ型がわからないけど、こんがらがったりしないの?

引数のデフォルト値

呼び出すとき、特に引数の指定がなかった場合に用いられる値。
p.95

>>> def greet(str="Hello, Python!! ", int=3):  #引数にデフォルト値を代入
...     print str * int
... 
>>> greet() #引数を指定しない
Hello, Python!! Hello, Python!! Hello, Python!! 
>>> greet("Goodbye!! ", 2)  #引数を指定
Goodbye!! Goodbye!! 
ローカル変数と戻り値

関数内で定義された変数はローカル変数となる。ローカル変数は関数の外では使えない。
一般的な名前空間と同じかな。


p.96 戻り値を使ってみる

>>> def power(a=2, b=3):
...     pow = a ** b
...     return pow
... 
>>> a = power()
>>> a
8

returnで戻り値。これ使うメリットがまだない・・・


p.98 ローカル変数の実験

>>> def foo(num):
...     a = 1    #関数内で定義
...     print a, num
... 
>>> foo(100)
1 100
>>> print a      #関数外で呼び出し
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined

ファイル処理

ファイルの読み込み

以下のファイル内容のfoo.txtを使う

aiueo
bbb
ccc

p.103 ファイルを読み込んでみる

>>> f = open("foo.txt", "r")
>>> s = f.read()
>>> s
'aiueo\nbbb\nccc\n'
>>> f.close()

open(),close()でファイルを開く/閉じる。読み込む場合はread()を使う

ファイルオブジェクトの読み込みメソッド

p.105

F.read(整数のサイズ)
ファイルから読み込みを行い、ファイルの終わりまでをひとつの文字列として返す。引数が指定されている場合、シーク位置からサイズ(バイト)分だけ読み込みを行う。
F.readline(整数のサイズ)
ファイルから1行読み込み、文字列として返す。引数を指定すると、読み込む行頭からの最大バイト数を指定できる。
F.readlines(整数のサイズ)
複数行を一度に読み込む。文字列を要素としたリストを返す。引数がない場合はファイルの最後までを読み込み、行に分割したリストを返す。引数を指定すると、行頭からの最大バイト数を指定できる。


F.read()の動作例とシーク位置の考察

>>> f = open("foo.txt", "r")
>>> s = f.read(5)  #先頭から5バイト
>>> s
'aiueo'
>>> t = f.read(5)  #次の5バイト
>>> t
'\nbbb\n'
>>> u = f.read()  #残り
>>> u
'ccc\n'

シーク位置(読み出し開始位置)の動きがわかりますね。


F.readline()の動作例

>>> f = open("foo.txt", "r")
>>> s = f.readline()
>>> s
'aiueo\n'
>>> f = open("foo.txt", "r")
>>> t = f.readline(2)  #2バイトまで読み込む
>>> t
'ai'


F.readlines()の動作例

>>> f = open("foo.txt", "r")
>>> s = f.readlines()
>>> s
['aiueo\n', 'bbb\n', 'ccc\n']
>>> f = open("foo.txt", "r")
>>> s = f.readlines(2)  #2バイトまで読み込む
>>> s
['aiueo\n', 'bbb\n', 'ccc\n']  #全然2バイトじゃないよ!

ちょっと、引数指定しても何ともないよ!

for文で1行ずつ読み込む

p.106

>>> f = open("foo.txt", "r")
>>> for line in f.readlines():
...     print line,
... 
aiueo
bbb
ccc

f.readlines() == ['aiueo\n', 'bbb\n', 'ccc\n']
というシーケンスだから1行ずつ表示できるわけですね、わかります。


もっと簡潔に書けます。
p.107

>>> f = open("foo.txt")
>>> for line in f:
...     print line,
... 
aiueo
bbb
ccc
ファイルを書き込む

p.107

ファイルオブジェクトの書き込みメソッド
F.write(文字列)
文字列を指定して、ファイルに対して書き出しを行う。戻り値なし
F.writelines(シーケンス)
文字列を要素に含むシーケンスを引数に与え、ファイルを書き出す。書き出すとき、改行文字を付加しないので注意。


F.write()の動作例

>>> str = "ama-ch "
>>> f = open("test.txt", "w")
>>> f.write(str * 3)
>>> f.close()
>>> g = open("test.txt")  #書き込み内容確認
>>> for look in g:
...     print look
... 
ama-ch ama-ch ama-ch 


F.writelines()の動作例

>>> f = open("foo.txt")       #こっから読み込んで
>>> g = open("test.txt", "w") #こっちへ書き込む。
>>> g.writelines(f.readlines())  #f.readlines() == ['aiueo\n', 'bbb\n', 'ccc\n']
>>> f.close()
>>> g.close()
>>> g = open("test.txt")  #書き込み内容確認
>>> for look in g:
...     print look,
... 
aiueo
bbb
ccc

書き込むとき、for文で1行ずつ読み込んだときと同じでf.readlines()をfで表せます。
慣れるまではfって書いちゃうとわかりにくそうだから素直にかいとこ。


失敗例

>>> f = open("foo.txt")
>>> g = open("test.txt", "w")
>>> g.writelines(f)
>>> f.close()
>>> for look in g:  #gに書き込んだ後、close()する前に中身を確認しようとする
...     print look,
... 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IOError: [Errno 9] Bad file descriptor

エラーになる!書き込みモード(wオプション)で開いたファイルオブジェクトをそのまま覗こうとしたから?


これでどうだ

>>> f = open("foo.txt")
>>> g = open("test.txt", "w+")  #オプションを読み書きできるモードにする
>>> g.writelines(f)
>>> f.close()
>>> for look in g:  #読めるかな?
...     print look,
...                 #読めなかった・・・
>>> g.readlines()   #シーケンスg.readlines()を確認
[]                  #あれ、空っぽだ!
>>> g.close()
>>> g = open("test.txt")  #読み込みモードで開き直し
>>> for look in g:
...     print look,
... 
aiueo  #読めた
bbb
ccc

あ〜シーク位置のこと考えてなかった!これが原因か!
g.writelines(f)の時点で、f,gのシーク位置は最後になる。
この最後のシーク位置からg.readlines()しようとしてたんだから、そりゃ空っぽになるわけか! オプションrでopenし直すとシーク位置が先頭にくるから普通に読み込んで表示できると。

そろそろ疲れたのでおしまい。

微妙にみんPyと違う結果になるところがあるな・・・
今日は色々できて楽しかった。今日も20ページちょい進んだ 昨日より長くやったのに同じとな><