制御構文 - 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のブロックに入りました')
... 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:
...
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サポーターズ
- 出版社/メーカー: 技術評論社
- 発売日: 2013/03/05
- メディア: 大型本
- 購入: 1人 クリック: 65回
- この商品を含むブログ (19件) を見る
制御構文 - リスト内包表記
■■リスト内包表記
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サポーターズ
- 出版社/メーカー: 技術評論社
- 発売日: 2013/03/05
- メディア: 大型本
- 購入: 1人 クリック: 65回
- この商品を含むブログ (19件) を見る
制御構文 - ループ
ちょっと日にちが空きましたが、
今回はループを勉強しました。
主題ではなく「not x (xが偽ならTrue)」の部分で躓いて無駄に時間を費やしてしまいました。
復習が足りてないですね。。。
以下、今回の備忘録です。
●4章 制御構文
■■ループ
■for
for ループ内変数名 in コンテナ
>>> for i in ["apple","orange","lemon"]:
... print(i)
...
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サポーターズ
- 出版社/メーカー: 技術評論社
- 発売日: 2013/03/05
- メディア: 大型本
- 購入: 1人 クリック: 65回
- この商品を含むブログ (19件) を見る
PHPとMySQLでハマった件
PHPとMySQLを使うプログラムでエラーに悩まされたので記録しておきます。
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。
↓
あっけなく成功。
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回めの接続までの時間。
・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逆引きハンドブック」の方が役に立つと思いました。
制御構文 - 比較演算子
ここ数日、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型(辞書)・・・キーと値のセットが全て同じなら等価
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
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サポーターズ
- 出版社/メーカー: 技術評論社
- 発売日: 2013/03/05
- メディア: 大型本
- 購入: 1人 クリック: 65回
- この商品を含むブログ (17件) を見る
制御構文 - 条件文
●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サポーターズ
- 出版社/メーカー: 技術評論社
- 発売日: 2013/03/05
- メディア: 大型本
- 購入: 1人 クリック: 65回
- この商品を含むブログ (17件) を見る
型とリテラル その2
前回は数学的な内容が辛かった分、
今回の学習はかなり楽でした。
以下、今回の備忘録です。
●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
スライスを使った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に追加している。
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サポーターズ
- 出版社/メーカー: 技術評論社
- 発売日: 2013/03/05
- メディア: 大型本
- 購入: 1人 クリック: 65回
- この商品を含むブログ (17件) を見る
*1:x, y