概要
- 完全にmemoです。
- といいつつも、どうやら本自体はMacが大前提に書かれてて(Windowsも対応とかは書いてはありますが…)、色々面倒だったので、Windows10 pro ver 1703 で どう頑張ったかの格闘記です。
- 誤植もそこそこ見かけてるので、その辺のフォローも入れていきます(編集者側の校正入ったんだろうか…章のタイトルとかで誤植がある)
- 正直、いつ終わるか or 放置するか分かりませんが、ひょっとしたら最後まで書くかもしれません
- ここは、この方がいいんじゃないの?や情報間違い等のマサカリは大歓迎ですので、バシバシコメント&編集リクエストへどうぞ
- 本のリンク:
この本を選んだ理由
- お決まりではありますが、「python 入門書」で Google 検索をした結果でヒットしたもの中から吟味して選びました。吟味した記事のリンクを参考に貼っております。
- 参考リンク
各章での対応メモ
Chapter01 プログラミング言語Python
python インストール
- win10だと BoW 上のpython も選択肢に入れそうになりますが、 エディタ(IDE)との連携が絶望的 なので、素直に python for windows を突っ込みましょう。
- この章を読んだ時点では 3.6.1 を導入しています
- 参考リンク
開発環境について
-
本の中ではAtom や Pycharm を挙げていましたが、せっかくWin10なんですし、vscode で pythonの開発環境を作りました
-
参考リンク
-
参考リンクにはなかったですが Code Runner という拡張機能がかなりお手軽にpythonコードの実行をサポートしてくれるのでお勧めです。(ctrl + alt + N で直接実行も可能)
jupyter notebook 導入
- これは普通にググって導入…
- 参考リンク
matplotlib 導入
- 本章ではいきなりimport で現れますが、普通にpipで入ってない状態だと動きませんので、事前にpipでインストールしてから導入です。
- 参考リンク
Chapter02 Pythonでプログラミングをはじめよう
変数名について
- 「日本語の変数名も可能(python3.x限定)」と「最初の1文字はアルファベット」って矛盾してなくないですか…
- なるほど?python3から 変数名にUnicode文字が使える から日本語も使える、って魂胆か。けど実情はギリシャ文字しか使えないから…うん、普通に ANSI文字のみ のほうが良いね、これ。
文字列
- 「+=」の複合演算子で追記するという仕様、どうなんだろ…便利そうだけど…
- 下記の2つは同じ結果、と。
a = 'testname'
a += 'dane'
a= 'testname'
a = a + 'dane'
型変換
- str()、int()、float() のお話。文字→数値変換の時に数値に置き換えられない文字が混じってるとエラーになる件、面倒そう…
- 「2バイトの数字」はint()やfloat()で受け付けるのに「2バイトのピリオド(小数点)」はfloat()でNGですか…中途半端感。
リスト
- 配列のようなものという認識。インデックスついてるし。
-
スライス で要素の一部を取り出すというの、面倒そう…
[start番号:end番号+1]
は直感的じゃない気が… -
val[1]
とval[1:2]
は同じ意味、という事だしねえ…
for文
- pythonの凄い特徴的な所ではあるんですが インデント自体に可読性以外の意味があって、正しくインデントされてないといけない という要素。
- 下記の例だと
- 「naka」複数回現れる
- 「soto」は1回のみ
- 最初の
print(i)
がインデントされていないとエラー -
print('gaiya')
は 余計な所でインデントされている という事でエラー
str_list = ['one', 'two', 'three', 'four', 'five']
for i in str_list:
print(i)
print('naka')
print('soto')
print('gaiya')
- range() は確かに便利そう。
if文 if~else 文 if~elif~else 文
- for文と同じで 判断後の処理をインデントする というルールがどうなんだ感はあるが、for文をそうしたんなら、if文もそうあるべきな気がする。
- あとはswitch(case)文ないのね…python。
組み込み関数、関数定義
- ローカル変数も含め 理解はこれでした。lintさんはめっさ怒ってたけど…関数の定義も最初にしないとエラーか…書く場所すら重要なのか。
'''
# こちらに書くとエラー
hyaku = 5
print(plus100(hyaku))
'''
def plus100(num):
hyaku = 100
return num + hyaku
# こちらはOK
hyaku = 5
print(plus100(hyaku))
モジュールのお話
-
import
とfrom
でモジュールをインポートするよ、というお話。 - 「import [モジュール名] as [別名]」の解説もここでされた
-
from
の使い道ってあるんだろうか…「特定の関数のみ使いたい」という需要が結構あるんだろうか
monk_fish_team = [158, 157, 163, 157, 145]
# import をそのまま使った書き方
import statistics
print(statistics.median(monk_fish_team))
# import ~ as を使った書き方
import statistics as sta
print(sta.median(monk_fish_team))
# fromを使った書き方
from statistics import median
print(median(monk_fish_team))
Chapter03 Pythonの基礎をマスターする
ディクショナリ(辞書)
- 他言語にあるハッシュと何が違うの?というお気持ちが…
- 辞書(ディクショナリ) - Python入門
辞書はマップ型の1つであり他のプログラミング言語ではハッシュや連想配列と呼ばれるものに似た機能を提供します。
- というか連想配列とかと一緒っぽいですね。そして ディクショナリ定義時のインデントはグダグダでも通る という悲しさ(pylintでは怒りますけどね)
- 下記の例が通ります
holiday = { "元日": "0101", "元日 振替休日": "0102", "成人の日": "0109",
"建国記念の日": "0211",
"春分の日": "0320",
"昭和の日": "0429",
"憲法記念日": "0503","みどりの日": "0504","こどもの日": "0505",
"海の日": "0717",
"山の日": "0811",
"敬老の日": "0918", "秋分の日": "0923",
"体育の日": "1009",
"文化の日": "1103", "勤労感謝の日": "1123",
"天皇誕生日": "1223"
}
if "0102" in holiday:
del holiday["0102"]
for key in holiday:
if "の日" in key:
print(key.replace('の', 'ノ'), holiday[key])
else:
print(key, holiday[key])
set(集合) について
- 配列とディクショナリ(ハッシュ)以外に複数値を持つ要素があるの…
- 主に数値演算用(OR,AND,XORとか)用に 要素の重複を排除した複数要素を持てる型 位の認識でよいのかね。
- 読んでいると、もともとリスト(配列)をset()関数でset型に変換できるようだ
- 逆(set型からリスト型)も可能なんだろうか?
- list() で可能だった。そりゃそーだよね…
hoge = {1, 2, 3, 4, 5, 4, 3, 2, 1}
fuga = [1, 3, 5, 7, 9, 7, 5, 3, 1]
# set型への変換含む
print(hoge^set(fuga))
# リスト型への変換含む
print(hoge, list(hoge)[-1], list(hoge))
タプル型について
- 要素の変更ができないリスト という例えはすごくしっくり来た。けど進んでタプルを定義する未来は混乱を招きそうな気もする…
- 下の例は前のset型の例にタプルも組み込んでみたらどうなるかな?というお話。普通に通ったけどね。
- 本の中では「緯度経度の所をタプルにする」という例が示されてたけど、まあリストでいいよね…
- そういや多次元タプルは作れるんだろうか? → 作れる。要素の追加/変更/削除ができないのでリストとの相違点はそこだけっぽい
- 最初は意識して使う必要はなさそうね…
hoge = {1, 2, 3, 4, 5, 4, 3, 2, 1}
fuga = [1, 3, 5, 7, 9, 7, 5, 3, 1]
ouie = (0, 2, 4, 6, 8, 6, 4, 2, 0)
taji = ((1,3,5), (2,4))
# 多次元のタプル
print(taji, taji[-1][-1], list(taji), set(taji))
# set型への変換含む
print(set(ouie)^set(fuga))
# リスト型への変換含む
print(ouie, ouie[-1], list(ouie)[-1], list(ouie))
# タプル型への変換含む
print(fuga, tuple(fuga), tuple(set(fuga)))
- これは完全な蛇足ですが「Python はまだ進歩の過程にある言語なので、他のシーケンスデータ型が追加されるかもしれません。」と言っているけど、括弧3種をすべて使って、別のシーケンス型を表現するにはどうするつもりなんでしょ。<>を使うとか?
if文の応用
- 不等号2つ書いて範囲を示せるのはいい仕様ですね。
- 文字列同士の比較時に不等号でも、 文字列を文字コードに変換して比較しているらしい はちょっと…不等号使ってる時点でエラー出してほしい感。
for i in range(10):
if 2 <= i < 5:
print("a:", i)
elif i != 7 and i != 1:
print("b:", i)
else:
print("c:", i)
ループの応用
-
おなじみの
break
、continue
のお話。forでもwhileでも使えますよ。 -
ただ、forやwhileで else文が定義できる(ループを抜けた後の処理を書く) は凄い仕様だな、と。
- 追加で分かったことだが、 breakでループを抜けるときはelse文のブロックは実行されない という事が分かった。 → else分かりにくくなること請け合い。(正常にループを終えたらelse文を追加で実行、ならありかも)
-
つまり下記は通る、と。(0,1,3,4,6,7,「owatta」を順番に出力して終わる処理)
for i in range(10):
if i == 5 or i == 2:
continue
elif i == 8:
break
else:
print(i)
else:
print('yatto')
print('owatta')
関数の応用
-
関数宣言文でデフォルト値を定義できる というのは自分の乏しい言語体験の中ではお初ですね。よく 型を縛る はCとかで見かけるけど。
-
あと、引数に入れる値を、 関数を呼び出す時点でキーワード名を付けて与えると、そこに入る仕様 も尖ってるよなぁ…
-
にしてもrange関数の仕様で (始めの値, 終わりの値+1) という仕様も直感的じゃないよなぁ…
-
例文にあったFizzbuzzを素直に書いてみましたよ、と。
def fizzbuzz(cnt_max=100, fizzmod=3, buzzmod=5):
for cnt in range(1, cnt_max+1):
if cnt%fizzmod == 0 and cnt%buzzmod == 0:
print("fizzbuzz", end=' ')
elif cnt%fizzmod == 0:
print("fizz", end=' ')
elif cnt%buzzmod == 0:
print("buzz", end=' ')
else:
print(cnt, end=' ')
print('')
cnt_max=10
# 後ろの引数を省略
fizzbuzz(cnt_max)
# 途中の引数を省略するにはキーワード名指定で書くしかなさそう
fizzbuzz(fizzmod=10, buzzmod=15)
-
蛇足なんだけど、引数の形にも複数あるの…
- 通常引数:ここには値を渡さないとエラーになる
- デフォルト引数:値を渡さなくてもよい引数
- 未定義引数:リストとか複数要素を渡すための引数(らしい)
- 未定義キーワード引数:未定義な変数(通常は辞書型で)を渡すための引数(らしい)
-
だったら素直に 関数の引数に型指定させてくれ と思ったのは私だけでしょうか。
-
参考:
-
あと、変数のスコープのお話がありましたね。基本 関数内ローカル と グローバル? の2つだけなんだろうか
- すげぇ、変数のスコープが 漏れる(伝播?) という概念がpythonには存在するのか、これは辛そうだ…
- あと、参考先で書いてたけど、多段で関数定義できるの…その場合の 関数自体のスコープ ってどこまでなんだろうか。変数と同じ?
- 参考 :
Chapter04 組み込み型を使いこなす
オブジェクトとしての組み込み型
-
[変数/関数名].[メソッド] のお話。例えばリスト内のindex値を出したい、というのであれば
[リスト型変数名].index([値])
で出せますよ、というお話。 -
型の一覧が紹介されてるんだけど、新たに bytes型 と bool型 というのが出ているんですが…読んだ限りではこういう認識で良いのかな?
- bytes型:str(文字列)型版タプル(要素の変更不可)
- bool型:True or Falseのみ
-
str型とbytes型を明確に宣言を分けたいときはどうすればいいんでしょうね…
-
複数要素を並べた型を シーケンス っていうらしいですよ。
-
あと mutable(ミュータブル,変更可能) と、 immutable(イミュータブル,変更不可) のお話も。リスト:タプル、str:bytes の関係ですかね。
数値型の操作
- 2進数、8進数、16進数のお話。
進数名 | 表記方法 |
---|---|
2進数 | 0b01 |
8進数 | 0o01 |
16進数 | 0x01 |
- int()で相互変換もできますよ、らしいです。
文字列型の操作
- ここかなり複雑な気がする…1つの項目で片付けるべきなんだろうか
文字列型で使えるメソッドのお話
- replace,split,join メソッドを使って文字列の置換、分割、連結をするお話。
- joinメソッドに渡すシーケンス型は何でもいいんだろうか(リスト or set or タプル)…
- 挙動は同じだった。但し違う知見は得られたけど。
- set型って要素の順番とかはぐちゃぐちゃなのね…と試してみて初めて得た知見。
$ cat temp.py
#!/usr/bin/env python
risuto1 = ["one", "two", "three"]
print(risuto1, '.'.join(risuto1))
risuto2 = ['one', 'two', 'three']
print(risuto2, '.'.join(risuto2))
setto1 = {"one", "two", "three"}
print(setto1, '.'.join(setto1))
setto2 = {'one', 'two', 'three'}
print(setto2, '.'.join(setto2))
tapuru1 = ("one", "two", "three")
print(tapuru1, '.'.join(tapuru1))
tapuru2 = ('one', 'two', 'three')
print(tapuru2, '.'.join(tapuru2))
mojiretsu = ' ichi ni san'
print(mojiretsu, mojiretsu.replace(' ', ' '), mojiretsu.split(), '-'.join(mojiretsu.split()))
$ python temp.py
['one', 'two', 'three'] one.two.three
['one', 'two', 'three'] one.two.three
{'one', 'three', 'two'} one.three.two
{'one', 'three', 'two'} one.three.two
('one', 'two', 'three') one.two.three
('one', 'two', 'three') one.two.three
ichi ni san ichi ni san ['ichi', 'ni', 'san'] ichi-ni-san
- エスケープシーケンスは他言語でもある仕様と変わらず、かな。
- そうでもないか。 同じ引用符を3つ重ねると改行を含んだ文字列を定義できる ようです。
- つまり下記2つは同じ定義。
"""1gyoume
2gyoume"""
"1gyoume\n2gyoume"
- raw文字列 というのがあるのか。引用符の前に「r」を付けるとエスケープを無視してそのままの文字列として認識するらしい。
- という事はraw文字列と3重引用符を合わせるとどうなるんだろ…
- なるほど、単純にraw文字列宣言はエスケープを無視して文字列として扱うだけか。
$ cat temp.py
#!/usr/bin/env python
mojiretsu1 = """1gyoume\n
2gyoume"""
mojiretsu2 = r"""1gyoume\n
2gyoume"""
print(mojiretsu1)
print(mojiretsu2)
$ python temp.py
1gyoume
2gyoume
1gyoume\n
2gyoume
-
次はformatメソッドの特集か。でもこれだるそうを感じる…取りあえずは printfの代替え 位の認識で臨んだ方がよさそう
-
ふーん…python2用の print文(フォーマット)もどっちもどっちだな…
import re
link_str = '<a href={}>{}</a>'
link_url = [ 'https://python.org', 'http://pypy.org', 'http://cython.org']
print(link_str)
for moji in link_url:
print(link_str.format(moji, re.sub(r"https?://", "", moji)))
- 色々な方はあるのはわかったが、使いこなせるか心配だ…
{: }
とか使い道が分からないのまであるし。 - f文字列は簡単なスクリプトには有効そうだけど、大規模なプログラミングには不向きそうでしょうがない。
リスト型の応用
-
sort()
返り値が 配列自体じゃない のか。となるとprint(list.sort())
みたいなことができないのか…めんどくさいな… - 複数の要素を「,」で区切ると、複数の要素に対応して代入が可能で、その要素は タプル型 で扱われるのか…これを アンパック代入 というらしい。
a = 1
b = 2
b, a = a, b
print(a, b)
2 1
- スライスも endの値は+1する というの…もう、こういうものだ、ってあきらめるしかなさそう。
- 仕様として
[最初のindex値:最後のindex値:取得間隔]
と、3つまで定義できるらしい。
lisuto1 = [1, 2, 3, 4, 5, 6, 7, 8, 9]
print (lisuto1[3:5])
print (lisuto1[3:100])
print (lisuto1[3:100:2])
ディクショナリ型を使いこなす
- へー…リスト型から dict() 関数を使うとディクショナリハッシュを作れるのか。
- 2つのリスト(タプルでもいいけど)を組み合わせてハッシュを作れないかしらん…
- 結論:zipという関数を組み合わせるとできる。
zip(key側のリスト, value側のリスト)
で指定してやればいい。 - 参考:Python Tips:リストから辞書を作成したい - Life with Python
- 結論:zipという関数を組み合わせるとできる。
- 2つの辞書を結合は結構大変だ、という事が分かった。いっぺんにやると魔境化するな、これ…
from itertools import chain
lisuto_key = [1, 2, 3, 4, 5]
lisuto_value = ('one', 'two', 'twree', 'four', 'five')
tsuika_hash = {6:'six', 7:'seven', 8:'eight'}
print(lisuto_key, lisuto_value)
print(dict(zip(lisuto_key, lisuto_value)), tsuika_hash)
print(dict(chain(dict(zip(lisuto_key, lisuto_value)).items(), tsuika_hash.items())))
if文と組み込み型
- if文でのTrue or Falseの定義のお話。
- Trueのパターン
- 数字の0以外(マイナスでもいいんか→OK。trueになる)
- 長さのある文字列
- 要素を持つシーケンス型
- 要素を持つディクショナリ
- Falseのパターン
- 数値の0
- Null ( ここで知ったが pythonで nullは
None
(大小英文字区別あり) と書くらしい) - 空の文字列
- 要素数が0のシーケンス型→つまり空という事
- 要素数が0の辞書型→つまり空という事
- Trueのパターン
- 下記はTrueってことですね。
deta = -1
if deta:
print(deta, 'ha Ture datte')
else:
print(deta, 'ha False datte')
for文と組み込み型
-
range関数とzip関数の応用のお話。
-
range関数は 要素1つだと終了の値 、要素3つだと開始、終了、増分 になると。
- enumerate というのがあるのか。日本語だと「数え上げる」らしい。どうやらループ1回につき、初期値0で1ずつ増えるらしい→いや初期値も指定できる模様。
- 参考:
-
zip関数の面白い動きとして、どちらかの要素がなくなるとループが終了する という動きをするね。へぇ…
lisuto_key = [1, 2, 3, 4, 5, 9, 10]
lisuto_value = ('one', 'two', 'twree', 'four', 'five', 'ten')
print(lisuto_key, lisuto_value)
for i, (a, b) in enumerate(zip(lisuto_key, lisuto_value), 1):
print(i,"banme:",a,b)
関数と組み込み型
- ここまで来ると、必要なの…って思われた アンパック代入 とか、 未定義引数 とかが必要になってきますよ、と。
- 関数からの出し入れで必要なのね…
- 関数にリストを渡したいときは、未定義引数を定義して、複数要素の値を タプル型 として受け取る、と。
- その前に 値渡し と 参照渡し という定義があって、???となってしまったぞ…
- 参考:Pythonの値渡しと参照渡し - amacbee's blog
- アンパック代入はreturnでリスト型で返す時に使う、と。
- 未定義キーワード引数 を使うと、未定義な引数まで渡せる、と。
- これ、リストを複数受け取りたいときはどうするんだろ…よくわからん。
- 参考:Pythonの関数の引数まとめ - Qiita
- ああ、これ (*args)を リスト型を渡すための引数 って本に書いてあるのが、ある意味ミスリードな気がしてきた。(未定義な引数に関してまとめて受け取って リストで渡すから であって、たまたまだよなぁ、と。)
pythonの文字列と日本語
- エンコードのお話。python3に関してはUNICODEが全ての中心、との事。まぁそうだよね…せっかく統一しようとして動いているものだし。
- その後、簡単な文字コード変換プログラムが来てました。こんなの。
- あと1行目にかけるなら、pythonスクリプトのエンコード指定をしておきましょう、という話がありました。
# coding: utf-8
moji = 'あいうえお'
enko = moji.encode('shift-jis')
deko = enko.decode('shift-jis')
print(len(moji), moji)
print(len(enko), enko)
print(len(deko), deko)
print(moji[0], enko[0], deko[0])
pythonのファイル処理
- いよいよ来ましたよ、ファイル処理。
- ファイルを開くには open() 関数を使う模様。C言語みたいに、open,closeは必要なのね。忘れたらどうなるんだろうね。メモリ破壊?
- 処理が終わった時に勝手にcloseされるっぽいね。メモリ節約する用途(LL言語なpythonでそれは…)か、一定期間内のみでファイルを参照させたいときに有用か。
- うーん、1行毎読む処理、 printする時にend文字を改行以外にする という仕様、地味にめんどくさいぞ…
fairu = open('./testfile.txt', 'r', encoding='utf-8')
for line in fairu:
print (line, end="")
fairu.close()
Chapter05 Pythonと関数型プログラミング
関数型プログラミングとは何か
- scalaとかhaskellとかerlangとかの説明かな、と思いつつ
- 関数型プログラミング は オブジェクト指向とは対になるパラダイムである らしいですよ、奥さん。
- reversed,sorted, lambda式の関数のお話。
- lambda式の関数のお話なんですが、わざわざ関数に投げる必要あるのかね、というお気持ちが…
- 下記参考サイトのsortedの例がしっくり来たかも。下記例題プログラムを見てると、何行圧縮してるんだよ、というお話ですね。
- 参考:Pythonの無名関数(lambda)の使い方 - Life with Python
l1 = [(7, 2), (3, 4), (5, 5), (10, 3)]
# lambdaを使った書き方
print(sorted(l1, key=lambda x: x[1]))
# lambdaを使わない書き方
# itemgetter関数のやり方しかなかったのでソース載せました
def aitmugettar(*items):
if len(items) == 1:
item = items[0]
def g(obj):
return obj[item]
else:
def g(obj):
return tuple(obj[item] for item in items)
return g
print(sorted(l1, key=aitmugettar(1)))
内包表記(コンプリヘンション)
- python3には3種類の内包表記があるらしい。
- リスト内包表記、辞書内包表記、set内包表記の3つ。
- 簡単なfor文回しでインデントはちょっと…というときには有用そうですね
l1 = [172, 165, 176, 150, 170, 170, 174, 165, 170, 163, 167, 165, 175, 171, 179, 156, 162, 160, 169, 165]
l2 = [172, 165, 176, 150, "17O", 170, 174, 165, 170, 163, 167, 165, 175, 171, 179, 156, 162, 160, 169, 165]
# リスト内包表記を使うとこんな感じ
print (sum([(height-(sum(l1)/len(l1)))**2 for height in l1])/len(l1))
# 普通にfor文使うとこんな感じ
count=0
for height in l1:
count += (height-(sum(l1)/len(l1)))**2
print(count/len(l1))
# if文を加えた例(文字列入りを弾く)
l3 = [x for x in l2 if isinstance(x, int)]
print (sum([(height-(sum(l3)/len(l3)))**2 for height in l3])/len(l3))
- 辞書内包表記を使うとkey, valueの反転を1行で書けてしまうのではという知見を得るなど。
# keyとvalueを反転するけど、valueに数値が入ってたら除外するよ、という例題
dhiku = {1:'one', 2:'two', 3:'three', 4:'four', 5:'five', 6:7}
print(dhiku)
print({b:a for a,b in dhiku.items() if not isinstance(b,int)})
- setは他と動きは似たようなものだし、いいか…
イテレータを使う
- pythonを勉強しているとたまに出てきてた イテレータ 。
- イテレータとは リストなどの複数の要素をもったデータ型に対して、順番にデータを取り出す機能を提供するオブジェクト 。このフレーズが一番しっくり来たかな
- イテレータ自体はfor文を宣言したときに暗黙的に実行されてたりする。明確にiter()関数、next()関数でも出来るみたい。
- んでもって、 何故イテレータという概念を個別に取り上げているのか ですが、データを取り込むときに、取り込むデータ量を意識する必要があるから に尽きるんだろうなぁ、と。
- 下記例はblというリスト型とイテレータを宣言しているiblというリストでの動きの違いを書いたもの。こういうふうに例題作りながらやってると理解は深まってる気がする
bl = [1, 3, 5]
ibl = iter(bl)
# イテレータを明確に宣言していないリストは状態を持ってないので…
print ("bl")
for kai in range(3):
print('{} kaime'.format(kai+1))
[print(cnt, end=', ') for cnt in bl]
print('')
# 明確にイテレータを定義していると…?
print ("ibl")
for kai in range(3):
print('{} kaime'.format(kai+1))
[print(cnt, end=', ') for cnt in ibl]
print('')
- 必要になった時だけデータを用意する 事を本では 遅延評価 を定義しているけどあってるんだろうか…サイトによっていう事全然違う件。(まぁ書きなぐりも多いからあれだけど)
ジェネレータを使う
-
ジェネレータとは、イテレータを簡単に定義するための仕組み らしいですよ、本が言うには。ほかのサイトだとイテレータを補完するためのオブジェクト とか言ってたところもあったよな…
-
pythonのイテレータ実装は 外部イテレータ 、ジェネレータのような仕組みを 内部イテレータ というらしい…???
- だれか、外部イテレータと内部イテレータの単純な比較を教えてください…
- 外部イテレータ:繰り返し等の制御をユーザが自ら行う
- 内部イテレータ:繰り返しの制御もお任せする
- こういう認識で良いんだろうか?
- 参考:cmag5.rd
- だれか、外部イテレータと内部イテレータの単純な比較を教えてください…
-
yield自体は「譲る」という意味があるらしい。(ほかの意味もあるっぽいけど)
-
確かにyield行に当たると、一旦関数を抜けて、値を保持し、次はnextが呼ばれるまで動かない という動きをするっぽいですな。
-
下記の例題だと、途中で「hajime」が出た所で止まって、通常の数字を出して、「owari」を出していることが分かる。
def get_primes(x=2):
while True:
print("hajime:",x)
for i in range(2, x):
if x%i == 0: break
else: yield x
print("owari:",x)
x += 1
i = get_primes()
for c in range(10):
print(next(i))
- ジェネレータ式、というのがあるのか…確かにこれは便利そう。
i = (x**2 for x in range(1,10))
for cnt in range(1,10): print(next(i))
# ちなみにこれと同じ。敢えてジェネレータ式を使ってる
for cnt in range(1,10): print(cnt**2)
高階関数とデコレータ
-
また謎の概念が出てきた…
-
ググって出てきた下記参考ページをじっくり読んでみる
-
なるほど? 高階関数とは、関数をデータとして扱うような関数 だと。具体的な例としては下記があると。
- 関数を受け取るような関数
- 関数を返すような関数(関数を生成する関数)
-
そしてついでに参考ページを読んでいると クロージャ と ラッパー関数 なるものが出てくる。 部分適用 って言葉もあったな…
- クロージャ:外側の関数のローカル変数にアクセスしている内側の関数
- ラッパー関数:既存の関数を使用する時に、別の処理を追加するような関数
- 部分適用:ある関数から、引数の一部を与えた状態の関数を新しく作る事(ラッパー関数の一種)
-
デコレータ は前述で出た ラッパー関数の定義を簡略化できる仕組み と認識しておけば間違いがなさそう。
-
しかし、やっぱりラッパー関数と関数デコレータの相関関係はよくわからないな…
-
やっと例題できた気がする…ここ難しくないですか。あと関数デコレータ、普通は別の関数名で保存しそうだし、いるのかな、これ…(関数デコレータだと同じ名前に関数の機能をラッピングする)
# 既存の関数に前処理と後処理をラッピングする関数
def trace(func):
def wrapper(argu):
print("** argu=%s" % argu)
ret = func(argu)
print("** ret=%s" % ret)
return ret
return wrapper
@trace # even_odd に traceをラッピングしているのをデコレータで書く
def even_odd(i):
if i%2 == 0: return "even"
else: return "odd"
# even_odd = trace(even_odd) をここに書いても同じ
for x in range(10 + 1):
print(even_odd(x))
- にしても本だと数ページの内容なのに、実際は濃すぎるな、ここ。
--- ここまで読んだ ---
Chapter06 クラスとオブジェクト指向開発
Chapter07 クラスの継承と高度なオブジェクト指向機能
Chapter08 モジュール
Chapter09 スコープとオブジェクト
Chapter10 例外処理
Chapter11 標準ライブラリを使う
Chapter12 Pythonとデータサイエンス
Chapter13 Python2
- 章タイトルと実際の中身が違う件。