福岡県だけどPythonを勉強する!

他言語を積極的に推奨する福岡県でPythonを勉強していく記録。

制御構文 - with

■■with

・withはwithブロックに入る時と出る時に__enter__メソッドと__exit__メソッドを呼ぶ。

・withは続く式を評価した結果をコンテキストマネージャとして利用する。

 

>>> with open('test.txt', 'a') as f:

...     f.write('テスト')

... 

3

>>>

 

コンテキストマネージャになれる

__init__(self,file_name)と

__enter__(self)と

__exit(self,type,traceback)

という3つのメソッドが定義された

WriteFileクラスをつくる。

 

>>> class WriteFile(object):

...     def __init__(self, file_name):

...         print('__init__が呼ばれました')

...         self.file_name = file_name

...     def __enter__(self):

...         print('__enter__が呼ばれました')

...         self.f = open(self.file_name, 'w')

...         print('ファイルが開きました')

...         return self.f

...     def __exit__(self, type, value, traceback):

...         print('__exit__が呼ばれました')

...         self.f.close()

...         print('ファイルが閉じました')

... 

>>>

 

 

withに続けてクラスを生成すると、

クラスの仕組みにより__init__が自動で呼ばれ、

引数(ファイル名を表す文字列)が渡される。

 

withはコンテキストマネージャを得ると、

コンテキストマネージャの__enter__を呼び出す。

 

__enter__は初期化コードを記述し、

必要に応じて値を返す。

(値は複数個返す事も可)

 

withは返された値(オブジェクト)をasに続けた一時変数に格納する。

 

__enter__で問題が無ければ処理がwithブロックへ移る。

 

withブロック終了後に__exit__が呼び出される。

(__enter__が正常終了した時点で__exit__の呼び出しが保証されている)

 

 

 

>>> with WriteFile('test3.txt') as f:

...     print('withのブロックに入りました')

...     f.write('寿限無寿限無・・・')

...     print('withのブロックから出ます')

... 

__init__が呼ばれました

__enter__が呼ばれました

ファイルが開きました

withのブロックに入りました

9

withのブロックから出ます

__exit__が呼ばれました

ファイルが閉じました

>>>

 

正常終了した場合はtype、value、tracebackにNoneが設定されて呼び出される。

例外が発生した場合は、

・typeに例外の種類

・valueに例外のインスタンス

・tracebackにトレースバック

が設定されて呼び出される。

 

例外の伝搬を抑制したい場合は__exit__からTrueを返す必要がある。

 

■closeする何かを簡単に扱う

ファイルのようにcloseして終了したいものには

closingというコンテキストマネージャを使う。

 

>>> from contextlib import closing

>>> with closing(open('test3.txt', 'w')) as f:

...     f.write('寿限無寿限無・・・')

... 

9

>>>

 

■ジェネレータを使うプログラムを簡単に扱う

 

>>> from contextlib import contextmanager

>>> @contextmanager

... def range_generator(max):

...     print('初期化コード')

...     try:

...         yield range(max)

...     finally:

...         print('終了コード')

... 

>>> with range_generator(5) as g:

...     for i in g:

...         print(i)

... 

初期化コード

0

1

2

3

4

終了コード

>>>

 

イマイチ理解出来ないのであとから復習する。

 

パーフェクトPython (PERFECT SERIES 5)

パーフェクトPython (PERFECT SERIES 5)

 

 

制御構文 - リスト内包表記

■■リスト内包表記

list Conprehension

既存のリストやジェネレータから新しいリストを作る。

>>> result = [x**2 for x in range(1,11)]

>>> print(result)

[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

 

通常のforループの場合

>>> for x in range(1,11):

...     result.append(x**2)

... 

>>> print(result)

[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

 

既存のリストから取り出した要素に対して処理だけでなく、

条件にマッチしたものだけを新しいリストに追加することも可能。

>>> result = [x**2 for x in range(1,11) if x%2 == 0]

>>> print(result)

[4, 16, 36, 64, 100]

 

forを続けて2重ループも可能。

>>> vec = [[1,2,3],[4,5,6],[7,8,9]]

>>> [num for elem in vec for num in elem]

[1, 2, 3, 4, 5, 6, 7, 8, 9]

 

通常のforループの場合

>>> result =

>>> for elem in vec:

...     for num in elem:

...         result.append(num)

... 

>>> print(result)

[1, 2, 3, 4, 5, 6, 7, 8, 9]

 

内包表記のメリット

・処理を簡潔に書ける。

・追加メソッドの呼び出しコストを軽減。

・処理時間のコストを削減。

 

■■その他の内包表記

セット内包表記

リストのの代わりに{}を使う。

>>> {x**2 for x in range(1,11)}

{64, 1, 36, 100, 81, 9, 16, 49, 25, 4}

 

辞書内包表記

>>> {x**2:x**2 for x in range(1,11)}

{64: 64, 1: 1, 36: 36, 100: 100, 81: 81, 9: 9, 16: 16, 49: 49, 25: 25, 4: 4}

 

リスト内包表記をジェネレータとして処理を遅延する事も可能。

[]の代わりに()を使う。

>>> res = (x**2 for x in range(1,11))

>>> next(res)

1

>>> next(res)

4

>>> next(res)

9

※ジェネレータとは・・・発電機、発生器、生成元などの意味を持つ英単語。ITの分野では、決められた条件などに基づいてデータやプログラムコードを自動的に生成するプログラムなどのことを指す。

 

パーフェクトPython (PERFECT SERIES 5)

パーフェクトPython (PERFECT SERIES 5)

 

 

制御構文 - ループ

ちょっと日にちが空きましたが、

今回はループを勉強しました。

 

主題ではなく「not x (xが偽ならTrue)」の部分で躓いて無駄に時間を費やしてしまいました。

 

復習が足りてないですね。。。

 

以下、今回の備忘録です。

 

 

●4章 制御構文

 

■■ループ

 

■for

for ループ内変数名 in コンテナ

 

>>> for i in ["apple","orange","lemon"]:

...     print(i)

... 

apple

orange

lemon

 

forループで任意の回数処理を繰り返したい場合には

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

 

>>> for i in range(5):

...     print(i)

... 

0

1

2

3

4

 

range関数は指定した数値の範囲内のiterableなオブジェクトを生成する。

※iterable・・・繰り返すことが出来る。

 

リストの要素を順に処理しつつ、インデックス番号も知りたい場合には

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

 

>>> for index, name in enumerate(["apple", "orange", "lemon"]):

...     print(index, name)

... 

0 apple

1 orange

2 lemon

 

ループが終わった後に実行したいプログラムがある場合は

elseを使う。

 

>>> for i in range(3):

...     print(i)

... else:

...     print("done")

... 

0

1

2

done

 

elseブロックはforループをしなかった場合にも実行される。

 

breakでループを出た場合はelseは実行されない。

>>> for i in range(1,4):

...     print(i)

...     if i == 2:

...         break

... else:

...     print("loop finished")

... 

1

2

 

continueはループ内のブロックを途中で終了し、次のループ処理へ飛ばす。

 

>>> for i in range(1, 4):

...     print(i)

...     if i == 2:

...         continue

...     print(i)

... 

1

1

2

3

3

 

■while

・whileは条件が条件が真の間だけループし続け、

条件が変わった時に終了する。

・whileはifのように評価される式をとる。

・whileはブロックを実行する前に毎回条件を評価し、

条件が真の場合にのみループを続ける。

 

>>> done = False

>>> while not done:

...     echo_text = input("echo > ")

...     if echo_text == "bye":

...         done = True

...         print("さようなら")

...     elif echo_text == "done":

...         done = True

...     else:

...         print(echo_text)

... 

echo > こんにちは

こんにちは

echo > どうもです

どうもです

echo > bye

さようなら

>>>

 

※ not x ・・・xが偽ならTrue、そうでなければFalse。

「done = False」でdoneが偽になる。

「not done」がFalseであり続ければ真なのでループし続ける。

 

 

・doneで抜けるケース

>>> done = False

>>> while not done:

...     echo_text = input("echo > ")

...     if echo_text == "bye":

...         done = True

...         print("さようなら")

...     elif echo_text == "done":

...         done = True

...     else:

...         print(echo_text)

... 

echo > done

>>>

 

ループの終了時にメッセージを表示するコード。

>>> done = False

>>> while not done:

...     echo_text = input("echo >")

...     if echo_text == "bye":

...         print("さようなら")

...         done = True

...     elif echo_text == "done":

...         done = True

...     else:

...         print(echo_text)

... else:

...     print("さようなら")

... 

echo >こんにちは

こんにちは

echo >てすと

てすと

echo >done

さようなら

>>>

 

for文と同様、whileのelseもループが回らなくても実行される。

>>> while False:

...     print("False")

... else:

...     print("done")

... 

done

 

※Falseは偽なのでループが実行されない。

 

for文と同様、breakで抜けた場合にはelseが適用されない。

>>> i = 0

>>> while 1:

...     i += 1

...     if i == 3:

...         break

...     print(i)

... else:

...     print('finished')

... 

1

2

 

※ 「while 1:」は「while True:」と同じで

breakするまで無限にループを繰り返す。

真を表せばいいので正の整数なら100でも999でもいい。

 

whileはfor文と同様、continueブロック内の処理を途中で終了して

次のループ処理にすすめる。

>>> i = 0

>>> while 1:

...     i += 1

...     if i == 3:

...         continue

...     else:

...         print(i)

...     if i == 5:

...         break

... 

1

2

4

5

>>>

 

パーフェクトPython (PERFECT SERIES 5)

パーフェクトPython (PERFECT SERIES 5)

 

 

PHPとMySQLでハマった件

PHPMySQLを使うプログラムでエラーに悩まされたので記録しておきます。

 

a.php

1.MySQLにアクセスしてSELECT。

2.約2時間かかる別の処理。

3.MySQLにアクセスしてINSERT INTO。

3の挿入が出来ていない・・・。

 

a.phpで何度もテストするのは時間がもったいないので規模を小さくしたb.phpを作成してテストしてみる。

 

b.php

1.MySQLにアクセスして1件をSELECT。

2.数秒で終わる別の処理。

3.MySQLにアクセスして10件ほどINSERT INTO。

あっけなく成功。

 

ここでa.phpに関するPHPのログを見てみる。

Error while sending QUERY packet.

 

php.iniのmax_allowed_packetの値を大きくしろと言ってる外人がいたので実行するも変化なし。

 

日本語の情報が引っかからなくて試行錯誤した末、

mysql_connectを読み込むrequire_onceが1回しか読み込めないからだと考え、

2回めのクエリの前に読み込むmysql_connectをrequireに変更してa.phpを実行。

Error while sending INIT_DB packet.

 

変化があった。

このエラーも日本語の情報が皆無。。。

 

a.phpとb.phpの違いといえば2回めの接続までの時間。

そこでMySQLタイムアウト絡みの記述を確認してみる。

・my.cnf

wait_timeout = 60

 

これって短いんじゃないか?

上記項目について検索してみると

「デフォルトの8時間じゃ短いから1年に変更した」

という記事などが引っかかる。

 

どうやら一度接続が切れると再接続出来ない事もあるとか。

 

というわけでwait_timeoutを28800(8時間)に変更。

念の為にinteractive_timeoutも28800に変更。

 

a.phpを実行したらうまくいきました。

 

60秒しか待ってくれないのに2時間も違う処理をしていればそりゃあタイムアウトしますよね。

 

タイムアウトで接続が切られて再接続出来なかっただけ

でした。検索の途中でデッドロックという文字を見かけたのはこれの事だったのかな。。。

 

何で60秒に変更していたのかは謎です。

 

さらに調べるとmysql_connectじゃなくてmysql_pconnectを使えば接続が切れないとの事。

 

mysql_pconnectに変更してweit_timeoutを60秒に戻してみてもしっかり動いてくれました。

(じゃあこっちがいいや。)

 

mysql_pconnectはPHP 5.5では非推奨なので次のバージョンで無くなりそうな気がしますが、connectの方も非推奨らしいので同じ事です。

 

いまさらPDOを覚えるのは面倒なので早くPythonをマスターしてSQLAlchemyでデータベースをいじれるようになりたいです。

 

p.s.

PHP逆引きレシピ 第2版」より「PHP逆引きハンドブック」の方が役に立つと思いました。

MySQL全機能バイブル ~現場で役立つAtoZ~

MySQL全機能バイブル ~現場で役立つAtoZ~

 

 

PHP逆引きハンドブック

PHP逆引きハンドブック

 

 

制御構文 - 比較演算子

ここ数日、PHPで上手くいかない事が何件かあって勉強があまり進みませんでした。

しょせん最下層ぺちぱーですから・・・。

 

前回から記事を節ごとに書く事にしました。

その方が後から見直す時に楽だからです。

 

以下、今回の備忘録です。

 

●4章 制御構文

■■比較演算子

 

比較演算子は < と >で値の大小を比較する。

ifやwhileなどのループで条件などに使う。

 

>>> 1 > 0

True

>>> 1 > 1

False

>>> 1.0 > 1

False

>>> 1 > 1.0

False

>>> 'b' > 'a'

True

 

大小の比較

・数値・・・数学的に比較し大小を判断。

・bytes・・・辞書順に比較し大小を判断。

・文字列・・・各文字をordし、順に比較し大小を判断。

※ord 文字に該当するアスキーコードを調べる。

 

>>> x = "あいう"

>>> y = "かきく"

>>> z = "あいあ"

>>> x < y

True

>>> x > z

True

 

・リスト・・・各要素を順に比較し要素について大小を判断。

素数が違う場合は存在する要素だけで判断。

>>> a = [1,2,3]

>>> b = [4,5,6]

>>> c = [4,5]

>>> d = [7]

>>> a < b

True

>>> a < c

True

 

dの要素数は1個だが、aの各要素(1、2、3)より7の方が大きい。

>>> a < d

True

 

要素が同じものなら要素数の多い方が大きい。

>>> e = [1,2,3,3]

>>> a < e

True

 

比較演算子は以下のように書ける。

>>> 0 < 1 < 2 < 3

True

 

同時に複数の比較演算が行えるので

人間の考える通りに書ける。

>>> def get_one():

...     print('get_one')

...     return 1

... 

>>> def get_two():

...     print('get_two')

...     return 2

... 

>>> def get_three():

...     print('get_three')

...     return 3

... 

>>> get_one() < get_two() < get_three()

get_one

get_two

three

True

 

>>> get_one() < get_two() and get_two() < get_three()

get_one

get_two

get_two

three

True

 

■等価

等価をテストするオペレータは ==

オブジェクトが同じ値であると言える時に「等価」と言う。

 

文字列・・・同じ文字列

数値・・・同じ値であれば等価

リスト・タプル・・・順序と値が等価であれば等価

map型(辞書)・・・キーと値のセットが全て同じなら等価

>>> "hoge" == "hoge"

True

>>> "hoge" == "hage"

False

>>> 1 == 1

True

>>> [1, 2, 3] == [1, 2, 3]

True

 

オブジェクトの型が違えば等価にはならない。

>>> 1 == "1"

False

>>> 0 == None

False

>>> False == None

False

 

数値同士なら整数と浮動小数点数で等価になる。

>>> 1.0 == 1

True

 

等価なオブジェクトが同一のオブジェクトとは限らない。

>>> x = [1,2,3]

>>> y = [1,2,3]

>>> x == y

True

>>> id(x)

140269941996000

>>> id(y)

140269941996432

 

■オブジェクトID

オブジェクトのID(Identity)・・・インタプリタがオブジェクトを管理する為のID。

インタプリタ・・・プログラムを実行するソフトウェア。

 

isキーワードは2つのオブジェクトが完全に同一かを確認出来る。

>>> x = [1,2,3]

>>> y = [1,2,3]

>>> x is y

False

 

※シングルトン・・・単体。一つしか生成しないということを保証する。

 

文字列・数値などのイミュータブル(変更不可)な型の場合はシングルトンでオブジェクトを生成する。

>>> x = "hoge"

>>> y = "hoge"

>>> x is y

True

>>> "hoge" is "hoge"

True

>>> 1 is 1

True

 

Noneもシングルトンで生成される。

>>> None is None

True

>>> False is False

True

>>> True is True

True

 

TrueやFalseもシングルトン。

 

 

いよいよ次からループ処理の勉強に入ります。

ちょっと嬉しいです。

パーフェクトPython (PERFECT SERIES 5)

パーフェクトPython (PERFECT SERIES 5)

 

 

制御構文 - 条件文

●4章 制御構文

 

■■条件文

 

ifステートメントで偽として扱われる項目

・None

・False

・0、 0.0、 0j

・空のシーケンス "" ()

・空のマップ型 {}

・空のセット set()

・__bool__メソッドが定義されているクラスで、Falseを返すもの。

・__len__メソッドが定義されているクラスで、0を返すもの。

 

上記以外の値は真。

 

Trueは真

>>> if True:

...     print("True")

... 

True

 

1は真

>>> if 1:

...     print("True")

... 

True

 

以下は偽になるのでブロックが実行されない。

>>> if :

...     print("True")

... 

>>>

 

 

elifは多言語のelse if。

 

 

>>> if False:

...     print("false")

... elif 1:

...     print("1")

... 

1

 

上から順に評価され、

最初の真のブロックを実行される。

>>> if False:

...     print("False")

... elif 1:

...     print("1")

... elif 0:

...     print("0")

... elif True:

...     print("True")

... 

1

 

ifもelifも偽なのでelseブロックが実行される。

>>> if False:

...     print("False")

... elif 0:

...     print("0")

... else:

...     print("default")

... 

default

 

■andとorとnot

・and、or、notは複数の条件を指定したい時に用いる。

 

・andで繋がれた条件は左から順に評価し、

「全てが真」だった場合にその条件式のブロックが実行される。

>>> def get_true():

...     print("call get_true")

...     return True

... 

>>> def get_false():

...     print("call get_false")

...     return False

... 

>>> if get_true() and get_true():

...     print("True")

... 

call get_true

call get_true

True

 

・orで繋がれた条件は左から順に評価し、

最初に「真が見つかった時点で」その条件式のブロックが実行される。

それ以降のorで繋がれた式は評価しない(無視)。

>>> if get_true() or get_false():

...     print("True")

... 

call get_true

True

>>> if get_false() or get_true():

...     print("True")

... 

call get_false

call get_true

True

 

 

条件式を否定したい時はnotを使う。

0じゃない→偽じゃない→真

>>> if not 0:

...     print("True")

... 

True

 

「1ではない」というだけなので偽というわけではない。

>>> if not 1:

...     print("False")

... 

>>>

 

・andとorの変わった動き。

>>> 1 and 2

2

>>> 0 and 1

0

>>> 1 or 2

1

>>> 0 or 1

1

 

andは左辺が真の時には右辺を返す。

左辺が偽の時は左辺を返す。

 

orは左辺が真の時は左辺を返す。

左辺が偽の時は右辺を返す。

 

考察

「andは偽を好み、orは真を好む」と考えたらいいか。。。

 

パーフェクトPython (PERFECT SERIES 5)

パーフェクトPython (PERFECT SERIES 5)

 

 

型とリテラル その2

前回は数学的な内容が辛かった分、

今回の学習はかなり楽でした。

 

以下、今回の備忘録です。

パーフェクトPython

●3章 型とリテラル その2

 

■シーケンス(Sequence)

シーケンスはオブジェクトをシーケンシャル(順番)に処理するためのデータ構造。

 

Pythonのシーケンス

・コンテナ

イテレータ

・ジェネレータ

 

シーケンスがサポートしている操作

 

x in s

sの要素にxと同じ要素があればTrue。無ければFalseを返す。

>>> s = 'abc'

>>> s = 'abcdefg'

>>> 'c' in s

True

 

x not in s

sの要素にxと同じ要素があればFalse。無ければTrueを返す。

>>> 'z' not in s

True

 

s + t

sとtを連結する。

>>> s + 'h'

'abcdefgh'

 

s * n、 n * s

sをn回連結する。

>>> s

'abcdefg'

>>> s * 2

'abcdefgabcdefg'

>>> 2 * s

'abcdefgabcdefg'

 

s[i]

sのi番目の要素を取り出す。ゼロオリジン。

※ゼロオリジン・・・数字の0から始まる数え方のこと。

>>> s[0]

'a'

 

s[i:j]

sのi番目の要素からj番目の前までの要素を取り出す。

>>> s[1:4]

'bcd'

 

s[i:j:k]

sのi番目の要素からj番目の前までの要素をk個ごとに取り出す。

>>> s[0:6:2]

'ace'

 

len(s)

sの要素数を取り出す。

>>> len(s)

7

min(s)

sの要素のうち一番小さいものを取り出す。

>>> min(s)

'a'

 

max(s)

sの要素のうち一番大きいものを取り出す。

>>> max(s)

'g'

 

s.index(i)

sの要素の中にiと同じものが最初にあったインデックスを返す。

>>> s.index('c')

2

 

s.count(i)

sの要素の中にiと同じものがいくつあるかを返す。

>>> s2 = 'abcabcabc'

>>> s2.count('a')

3

 

■文字列/バイト列

Pythonの文字列はstr。

strは内部でUnicodeデータを保持する。

strは符号化されたテキストとして使う。

スクリプトファイル中のテキスト文字列はファイルのエンコーディングに従って

strオブジェクトをUnicodeに変換する。

 

python3はスクリプトファイルがUTF-8で記述していると想定する。

 

ファイルのエンコーディング指定

1行目、もしくはシェバン(shebang)がある時は

2行目に以下を記述。

 

# coding: UTF8

 

または

# coding=UTF8

 

Emacsの場合は

# -*- coding:UTF8 -*-

 

>>> x = 'テスト'.encode('UTF8')

>>> x.decode('UTF8')

'テスト'

 

符号化した文字コードと違う文字コードで復号化しようとすると

UnicodeDecodeErrorを送出する。

 

>>> x.decode('cp932')

Traceback (most recent call last):

  File "<stdin>", line 1, in <module>

UnicodeDecodeError: 'cp932' codec can't decode byte 0x86 in position 2: illegal multibyte sequence

 

■イミュータブル

str型とbytes型は共にイミュータブル(変更不能)オブジェクト。

オブジェクト自身の状態を変更出来ない。

変数に割り当てているイミュータブルなオブジェクトの状態を変えるには、

新しいオブジェクトを作成して変数の指し示す先を新しいオブジェクトに変更する。

 

>>> s = 'spam'

>>> id(s)

139751185244264

>>> s = 'egg'

>>> id(s)

139751177393240

 

関数id()はオブジェクトの固有番号を返す。

 

■バイト配列型

バイト配列型 = バイト配列 = bytearray型

 

bytes型と違ってbytearray(バイト配列型)はミュータブルなバイト列。

違いはミュータブルであることだけ。

bytearrayはbytearrayコンストラクタで生成する。

 

bytearray(string, encoding[, errors])

 

コンストラクタとは・・・オブジェクトの生成時に呼び出される特殊な関数。

初期化などをここで行う。

http://e-words.jp/w/E382B3E383B3E382B9E38388E383A9E382AFE382BF.html

 

>>> ba1 = bytearray()

>>> ba1.append(115)

>>> ba1.append(112)

>>> ba1.append(97)

>>> ba1.append(109)

>>> ba1

bytearray(b'spam')

 

 

bytearrayのその他の生成方法

・整数のイテレータを渡す

>>> ba2 = bytearray([115,112,97,109])

>>> ba2

bytearray(b'spam')

 

・文字列とそのエンコーディングを渡す

>>> ba3 = bytearray('日本語','UTF8')

>>> ba3

bytearray(b'\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e')

>>> ba3.decode('utf8')

'日本語'

 

・bytesを渡す

>>> ba4 = bytearray(b'egg')

>>> ba4

bytearray(b'egg')

 

・整数でサイズを指定して渡す

>>> ba5 = bytearray(128)

すべての要素が0で初期化される。

 

bytearrayの要素は0-255までの整数。

bytearrayからstrへの変換メソッドは

 

decode('utf8','strict')

もしくは

decode(encoding='utf8', errors='strict')

 

日本語の1文字は3バイトなので

bytearray型では「スパム」の要素数は9になる。

>>> ba_nihongo = bytearray('スパム', 'utf8')

>>> ba_nihongo

bytearray(b'\xe3\x82\xb9\xe3\x83\x91\xe3\x83\xa0')

>>> len(ba_nihongo)

9

>>> ba_nihongo.decode('utf8','strict')

'スパム'

>>> len(ba_nihongo.decode('utf8','strict'))

3

 

errorsに指定可能なオプションは以下

strict・・・変換に失敗した際にUnicodeDecodeErrorを送出する。

ignore・・・問題のあるデータを無視する。

replace・・・問題のあるデータを「?」などの安全な文字に置換。

 

生成したbytearrayは要素を指定して値を変更出来る。

>>> ba = bytearray('spam', 'utf8')

>>> ba[1] = 104

>>> ba

bytearray(b'sham')

 

■リスト(lists)

 

順序を保ちながらオブジェクトをリストする。

種類を問わずに格納出来る。

数値・文字列・インスタンス・None・list・・・。

 

Pythonのリストはミュータブル(変更可能)。

 

>>> x = [1, 2, 3.0, "a", "b", "c"]

 

■インデクシング(シーケンス番号を使ったアクセス)

 

listのインデックスはゼロオリジン

"zero-based indexing"

(1オリジンの場合は"one-based")

 

>>> x[0]

1

>>> x[1]

2

>>> x[5]

'c'

 

範囲外の場合はIndexErrorを送出。

 

>>> x[6]

Traceback (most recent call last):

  File "<stdin>", line 1, in <module>

IndexError: list index out of range

 

ネガティブインデックス(負のインデックス)

>>> x[-1]

'c'

>>> [-2]

[-2]

>>> x[-2]

'b'

>>> x[-4]

3.0

>>> x[-6]

1

>>> x[-7]

Traceback (most recent call last):

  File "<stdin>", line 1, in <module>

IndexError: list index out of range

 

■スライス

listからサブリストを得る為のシンタックス。

※シンタックス・・・構文・構文規則

 

・インデックスかネガティブインデックスを使用する。

・開始位置から終了位置の一つ前までの要素を取り出す。

 

>>> x[1:2]

[2]

>>> x[1:4]

[2, 3.0, 'a']

>>> x[2:-1]

[3.0, 'a', 'b']

>>> x[-3:-1]

['a', 'b']

 

間違った順序や範囲外を指定すると

空のlistが返る。

>>> x[-1:-3]

>>> x[-3:-7]

 

 

スライスでは開始位置と終了位置を省略出来る。

>>> x[1:]

[2, 3.0, 'a', 'b', 'c']

>>> x[:3]

[1, 2, 3.0]

>>> x[:-2]

[1, 2, 3.0, 'a']

>>> x[:]

[1, 2, 3.0, 'a', 'b', 'c']

 

イテレーション

イテレーション・・・繰り返すこと。反復。

 

listは全要素に対して順に何らかの処理をする際に用いられる事が多い。

ループのシンタックスで全要素へ順にアクセス出来る。

>>> for item in x:

...     print(item)

... 

1

2

3.0

a

b

c

 

for inシンタックスのループ対象はlistであれば良い。

>>> x = [1, 2, 3.0, 'abc']

>>> for c in x[3]:

...     print(c)

... 

a

b

c

>>> for item in [1, 2, 3, 4]:

...     print(item)

... 

1

2

3

4

 

■リストの更新

要素をlistに追加するにはappendメソッドを使う。

>>> x =

>>> x.append("spam")

>>> x

['spam']

>>> x.append("eggs")

>>> x

['spam', 'eggs']

 

要素をlistから削除するにはremoveメソッドを使う。

>>> x.remove("eggs")

>>> x

['spam']

>>> x.remove("spam")

>>> x

 

要素がlistに無い場合はValueErrorを送出する。

>>> x.remove("abc")

Traceback (most recent call last):

  File "<stdin>", line 1, in <module>

ValueError: list.remove(x): x not in list

 

インデックスを使ってlistの要素を変更する事が出来る。

>>> x = ["spam", "eggs"]

>>> x[1] = "hoge"

>>> x

['spam', 'hoge']

 

スライスを使ったlistの変更

>>> x = [1, 2, 3, 4, 5]

>>> x[1:4]

[2, 3, 4]

 

スライスの範囲に右辺の要素を割り当てる。

>>> x[1:4] = ["spam", "eggs"]

>>> x

[1, 'spam', 'eggs', 5]

 

reverseメソッドで順序が反対になる。

>>> x.reverse()

>>> x

[3, 2, 1]

 

sortメソッドでソートする。

>>> x = [1, 0, 1, 7, 4, 1, 4, 7, 3, 3]

>>> x.sort()

>>> x

[0, 1, 1, 1, 3, 3, 4, 4, 7, 7]

 

▼考察

スライスは元のオブジェクトを変更しないけど

append、removeなどの

「メソッド」はオブジェクト自体を変更している。

 

■リスト内包表記(リストコンプリヘンション)

リスト内包表記はループと条件を使って新しいlistを生成する

特別なシンタックス。

リスト内包表記は通常のfor inループよりも高速。

 

>>> [i for i in range(10) if i % 2 == 0]

[0, 2, 4, 6, 8]

 

>>> [str(i) for i in range(10) if i % 2 == 0]

['0', '2', '4', '6', '8']

 

 

▼考察

[式 ループ 条件]という表記で、

条件に従いながらループ部分を繰り替えし、

ループの度に先頭の式を適用してからlistに追加している。

 

Pythonチュートリアル

http://docs.python.jp/3.3/tutorial/datastructures.html

リスト内包表記は、括弧の中の式、for句、

そして0個以上のforかif句で構成されます。

 

ifだけじゃなくてforが後にくる事もある。

以下の2つは等価。

 

>>> [(x,y) for x in [1,2,3] for y in [3,1,4] if x != y]

[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]

 

 

>>> combs = []

>>> for x in [1,2,3]:

...     for y in [3,1,4]:

...         if x != y:

...             combs.append*1

... 

>>> combs

[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]

 

■タプル(tuple)

タプルはイミュータブル(変更不可)なシーケンス型。

格納する値は自由。

要素が1つの場合はタプルであることがわかるように

末尾にカンマを付けて(1,)と記述する。

末尾のカンマで要素数が増えることはない。

listやdictもカンマを最後に付けることが可能。

 

インデックスでのアクセスが可能。

要素の変更は不可。

 

>>> x = (1,2,3,"a","b","c")

>>> x[0]

1

>>> x[3]

'a'

>>> x[3] = "z"

Traceback (most recent call last):

  File "<stdin>", line 1, in <module>

TypeError: 'tuple' object does not support item assignment

>>> y = (1)

>>> type(y)

<class 'int'>

>>> y = (1,)

>>> type(y)

<class 'tuple'>

 

■tupleの利点

listよりも処理が高速。

ハッシュ化が可能。

ハッシュ化が可能なので辞書型(dict)のキーに利用出来る。

※ハッシュ化・・・ハッシュ関数を用いてデータをある一定の値域にマッピングすること。

http://moguno.hatenablog.jp/entry/20110502/p1

 

■set(セット)

ユニークなオブジェクトの集合を保持するシーケンス。

同じオブジェクトの追加を無視する。

ハッシュ化出来ないものは追加出来ない。

>>> x = {1, 2, "a", "b"}

 

リストからの生成にはset関数を使う。

>>> x = set([1, 2, "a", "b"])

 

listはミュータブルなので格納出来ない。

>>> x = {[1, 2, 3], "abc"}

Traceback (most recent call last):

  File "<stdin>", line 1, in <module>

TypeError: unhashable type: 'list'

 

tupleはイミュータブルなので格納出来る。

>>> x = {(1, 2, 3), "abc"}

 

■セットの操作

更新用のメソッド

・add

・remove

>>> x = {1, 3, "abc"}

>>> x.add(2)

>>> x

{3, 1, 2, 'abc'}

>>> x.remove(3)

>>> x

{1, 2, 'abc'}

 

存在しない場合はKeyError

>>> x.remove(5)

Traceback (most recent call last):

  File "<stdin>", line 1, in <module>

KeyError: 5

 

discardを使えば要素が存在しなくてもエラーが出ない。

>>> x = {1, 2, 3, "abc"}

>>> x.discard(3)

>>> x

{1, 2, 'abc'}

>>> x.discard(5)

>>> x

{1, 2, 'abc'}

 

イテレーション

setはシーケンス型なのでイテレート処理をサポートしている。

ループでのイテレートが可能。

順番はサポートされない。

>>> x = {1, 2, 3, "abc"}

>>> for y in x:

...  print(y)

... 

3

1

2

abc

 

■setの利点

ユニオン・インターセクション・ディファレンスなどの処理で

高速に動作する。

 

■ユニオン(Union合併)

setの合併

>>> store1 = {7, 9, 2}

>>> store2 = {18, 22, 3, 7, 12}

>>> store1.union(store2)

{2, 3, 7, 9, 12, 18, 22}

 

3つ以上の合併はコンマの後に引数を増やす。

>>> store3 = {11, 6, 9, 15}

>>> store1.union(store2,store3)

{2, 3, 6, 7, 9, 11, 12, 15, 18, 22}

 

■インターセクション(交差・積集合)

2つのsetに含まれる要素を抽出。

>>> store1 = {7, 9, 2}

>>> store2 = {18, 22, 3, 7, 12}

>>> store1.intersection(store2)

{7}

 

3つ以上の場合は引数を増やす。

>>> store1 = {7, 9, 2}

>>> store2 = {18, 22, 3, 7, 12, 9}

>>> store3 = {11, 7, 3, 6, 9, 15}

>>> store1.intersection(store2,store3)

{9, 7}

 

ディファレンス(Difference 差集合)

ディファレンスは元の集合のみに存在し、

他の集合には存在しない部分。

元になる集合に意味を持つ。

>>> store1 = {7, 9, 2}

>>> store2 = {18, 22, 3, 7, 12, 9}

>>> store1.difference(store2)

{2}

 

順番を変えてみる

>>> store2.difference(store1)

{18, 3, 12, 22}

 

3つ以上の場合は引数を増やす。

>>> store1 = {18, 22, 3, 7, 12, 9}

>>> store2 = {7, 9, 2}

>>> store3 = {11, 7, 3, 6, 9, 15}

>>> store1.difference(store2,store3)

{18, 12, 22}

 

シンメトリックディファレンス

どちらかの集合にだけ含まれる要素を抽出。

順番は関係ない。

>>> store1 = {18, 22, 3, 7, 12, 9}

>>> store2 = {7, 9, 2}

>>> store1.symmetric_difference(store2)

{2, 3, 12, 18, 22}

>>> store2.symmetric_difference(store1)

{18, 3, 22, 12, 2}

>>> (store1.symmetric_difference(store2) == store2.symmetric_difference(store1)) 

True

 

■サブセット・スーパーサブセットとディスジョイントセット(素集合)

セットAにセットBの要素が全て含まれている場合、

・セットAはセットBのスーパーセット。

・セットBはセットAのサブセット。

 

>>> colors = {"red","blue","green","yellow","purple","orange"}

>>> subset = {"purple","green"}

>>> subset.issubset(colors)

True

>>> colors.issuperset(subset)

True

 

1つも共通の要素が含まれないセットの事を

ディスジョイント(素集合)という。

2つのセットがディスジョイントかどうかは

isdisjointメソッドで確認する。

 

>>> primary = {"red","blue","green"}

>>> art_primary = {"magenta","cyan","yellow"}

>>> primary.isdisjoint(art_primary)

True

 

■辞書型(Dictionaries)

キーと値を対応させたデータ型をマップ型と呼ぶ。

リスト・タプル・インスタンス・他の辞書型オブジェクト・etc・・・

Pythonのオブジェクトならどんなものでも格納出来る。

順番はサポートしていない。

>>> d = {

...         'key1': 'Value1',

...         'key2': 'Value2',

...         'key3': 'Value3',

... }

>>> d

{'key3': 'Value3', 'key2': 'Value2', 'key1': 'Value1'}

 

行をわけなくても作成出来る・・・。

>>> d2 = {'key1': 'Value1', 'key2': 'Value2',}

>>> d2

{'key2': 'Value2', 'key1': 'Value1'}

 

■インデックスアクセス

キーを使って値を取り出せる。

>>> d['key1']

'Value1'

>>> d['key2']

'Value2'

>>> d['key4']

 

存在しないキーを使うとKeyError

Traceback (most recent call last):

  File "<stdin>", line 1, in <module>

KeyError: 'key4'

 

in構文で辞書にキーが登録されているか確認出来る。

これで確認しておけばKeyErrorを回避出来る。

>>> 'key1' in d

True

>>> 'key4' in d

False

 

getメソッド

キーが登録されていない場合に

第2引数をデフォルト値として使用出来る。

指定が無い場合はNone(非表示)が返る。

>>> d.get('key1')

'Value1'

>>> d.get('key4')

>>> d.get('key4')

>>> d.get('key4', 'default')

'default'

>>> a = d.get('key4')

>>> a is None

True

 

 

>>> value = d.get('key4')

>>> if value:

...     print(value)

... else:

...     print("key4 does not exist!")

... 

key4 does not exist!

 

イテレーションアクセス

辞書の全ての要素をイテレーションするには、

inシンタックスでfor x in yのようにすると

すべてのキーをイテレート出来る。

>>> for key in d:

...     print(key)

... 

key2

key3

key1

 

値をイテレートするにはvaluesメソッドを使う。

>>> for value in d.values():

...     print(value)

... 

Value2

Value3

Value1

 

値とキーの両方をイテレートするにはitemsメソッドを使う。

>>> for key, value in d.items():

...     print(key, value)

... 

key2 Value2

key3 Value3

key1 Value1

 

■辞書の更新

※アサイン・・・割り当てる。

 

・既存の値を変更

インデックスを指定してアサインする。

>>> d['key1'] = 'NewValue1'

>>> d['key1']

 

・キーと値を追加

新しいキーでアサインする。

'NewValue1'

>>> d['newkey'] = 'NewValue1'

>>> d

{'newkey': 'NewValue1', 'key2': 'Value2', 'key3': 'Value3', 'key1': 'NewValue1'}

 

delメソッド・・・キーと値の削除を行う。

>>> del d['newkey']

>>> d

{'key2': 'Value2', 'key3': 'Value3', 'key1': 'NewValue1'}

 

popメソッド・・・値を取り出しつつ、キーと値の削除を行う。

>>> d.pop('key2')

'Value2'

>>> d

{'key3': 'Value3', 'key1': 'NewValue1'}

 

 

popメソッドはデフォルト値を指定するとエラーを出さずに処理を行う。

>>> d.pop('key2', 'default')

'default'

 

辞書型の削除はpopメソッドにデフォルト値を設定して行った方が

エラーを出さなくて済むので便利。

 

■辞書の順序

辞書型は順序が保証されない。

順序が重要な際はOrderedDictを使う。

>>> from collections import OrderedDict

>>> od = OrderedDict()

>>> od['b'] = 1

>>> od['1'] = 2

>>> od['a'] = 3

>>> for k, v in od.items():

...     print('{}:{}'.format(k, v))

... 

b:1

1:2

a:3

>>> od

OrderedDict([('b', 1), ('1', 2), ('a', 3)])

 

■None型

値が存在しない場合やアンセットしたことを明示する場合に利用する。

 

>>> d = {'key1': 'Value1', 'key2': 'Value2'}

>>> user_key = input("Key: ")

Key: key1

>>> value = d.get(user_key, None)

>>> print(value)

Value1

>>> user_key = input("Key: ")

Key: 

>>> value = d.get(user_key, None)

>>> print(value)

None

 

Noneは常に偽として評価される。

>>> if None:

...     print('None is true!')

... else:

...     print('None is false!')

... 

None is false!

 

Noneなのか偽なのか確認したい場合にはisを使う。

>>> y = None

>>> if y is None:

...     print("y is None")

... 

y is None

 

FalseがNoneではなく偽。

>>> y = False

>>> if y is None:

...     print("y is None")

... else:

...     print("y is not None")

... 

y is not None

 

 

パーフェクトPython (PERFECT SERIES 5)

パーフェクトPython (PERFECT SERIES 5)

 

 

*1:x, y