FrontPage / Learning Programming / 2015 / 2nd Semester

Learning Programming

2015年後期 概要

目的
自然言語処理100本ノックを,Python の言語仕様,good parts,best practice,よくハマる罠などを確認しながらじっくり解く.
日時
月曜日 13:00-14:30
参加者
折田 (naho),横井 (yokoi),上村 (may-u),鈴木 (m-suzuki),ダワ (dava),ゼン,Diana (dianags)
TA
山口 (k.yamaguchi),佐々木 (aki-s),高橋(諒) (ryo-t),五十嵐 (igarashi)
問題
http://www.cl.ecei.tohoku.ac.jp/nlp100/
http://www.cl.ecei.tohoku.ac.jp/local/?nlp100-%CE%B2 (内部ページ)
回答
http://www.cl.ecei.tohoku.ac.jp/~igarashi/yuru_nlp/index.py (内部ページ)
/home/igarashi/yuru_nlp/{username}/ に「問題番号を0埋め3桁.py」(e.g. 000.py) を up
前期分: http://www.cl.ecei.tohoku.ac.jp/~takase/nlp100/index.py (内部ページ)

参考資料

  • 分からないことがあったら…
    • Python の言語仕様や「Python っぽい書き方」が知りたければ Python 関係の資料にあたる.
    • 「オブジェクト指向って何?」「型って何?」「スコープって何?」という疑問は,プログラミング全般に書かれている書籍や,別言語の参考書で解決できるかもしれない.
    • Linux コマンドの使い方や,バージョン管理ソフト(e.g. git), ターミナルマルチプレクサ(e.g. tmux), パッケージ管理ソフト(e.g. homebrew), エディタ(e.g. vim)などの使い方で困っているならそれ専用の資料に当たる.
    • 何について困っているのか考えましょう.

Python

リファレンス・リンク集

情報を取り出すための基本コマンド

  • `help(command)` -> docstring がページャで開かれる.`command?` でも print されるが,場合によっては短縮版.
  • `dir(obj)` -> オブジェクトに紐づくプロパティ名やメソッド名の一覧が表示される.
  • `type(obj)` -> オブジェクトの型が表示される.

導入・全体像など

Good Parts

  • 『Python Cookbook』
    • 日本語版は, 版が古く, かついくつかの章が省略されている
  • 『エキスパートPythonプログラミング』
    • Good Parts および Python ちっくなソフトウェア工学

コーディング規約・スタイルガイド

Tools

  • Jupyter
    • GUI インタラクティブインタプリタ, 兼 markdown メモ, 兼 図表ビューア
    • スピーディにプログラムの第1稿を作る際の必須ツール
    • matplotlib (seaborn) との相性も良く, 実験でも大変便利
  • Online Python Tutor
    • プログラムの動き (メモリが書きかわる様子) を視覚化

プログラミング全般,各種パラダイム

  • 『プログラマの考え方がおもしろいほど身につく本』(目次)
  • 『コーディングを支える技術』(目次)
  • 『リーダブルコード』

Linux,各種ツール

  • 全般
    • 『新しい Linux の教科書』
  • シェル
    • 『zsh の本』
  • バージョン管理
    • 『GitHub 実践入門』

予定・記録

#05 2015/11/16(Mon) 13:10-15:05

参加者

  • 横井,ダワ
  • (TA) 山口,佐々木,高橋

解いた問題

  • 014-016 (3問)

Tips

  • seq[:n] で n>len(seq) だった場合もよきに計らってくれる (末尾以後の無視され,seq[:] が返る)
  • 入出力
    • ファイルオブジェクトの確保
      • sys.stdin の __exit__() メソッド(ある!)を呼び出す必要は特にないので, `with sys.stdin as f` は不要
  • 014
  • pandas
    • jupyter との共用が前提.interactive に表の状態を可視化できる.(セルの最後の行の評価結果がデータフレームであれば,そのまま見やすく出力される)
  • any, all

#04 2015/11/09(Mon) 13:00-14:40

参加者

  • 横井,上村,鈴木,佐藤,ダワ,Diana
  • (TA) 山口,佐々木,高橋

解いた問題

  • 009-013 (5問)

Tips

  • ファイル末尾の改行:
  • list(文字列) → 文字のリスト
    • `list('hoge')` -> `['h','o','g','e']`
  • スライスはコピーを返す.
    • `x=range(5); random.shuffle(x[:])`: x は shuffle されない.
  • str.split() で separator を省略すると,連続したホワイトスペースがひとつのセパレータと見なされる.cf. separator として `' '` (ひとつの空白) を指定
    • `'foo baa'.split()` -> `['foo','baa']`
    • `'foo baa'.split(' ')` -> `['foo','','baa']`
  • import 式: e.g., `__import__('random')`
    • グローバル領域の名前「モジュール名」を汚さない. (function スタックには積まれるので再利用性が下がりすぎることはない?)
    • lambda 式などで使い捨てするか,別の特定の変数に代入して使う?
    • ミドルウェアのバージョン違いを呼び出したいなど,モジュール名を動的に指定したいときにも便利.
    • `import somemodule as sm` と `sm = __import__('somemodule')` は等価?
  • random
    • random.shuffle(seq) は seq 自体を書き換える.値は返さない?
    • `random.sample(population, k)`: 母集団 (population) から k 個の標本を非復元抽出 (重複なしの sampling) をして結果のリストを返す
    • 標準ライブラリの random よりも numpy.random の方が偏りが少ないので,特に数値計算における乱数生成においては numpy.random を用いるべき (python/numpy - 機械学習の「朱鷺の杜Wiki」)
  • 基本的には generator 式の方が explicit なリストを作るよりも時間計算量も空間計算量も有利.
    • ただし,str のリストを join する場合は、はじめからリストにした方が速い.
  • `sorted(list, key=f)` f は list の要素から実数への関数.x を f(x) をキーに昇順に並べ直したリストを返す.
    • e.g., `sorted([['a',1],['b',3],['c',2]], key=(lambda x:x[1]))` -> `[['a', 1], ['c', 2], ['b', 3]]`
  • 入出力
    • ファイルオブジェクトの確保
      • 標準入力: `import sys; f = sys.stdin` (同様に `sys.stdout`, `sys.stderr` で標準出力,標準エラー出力が取り出せる)
      • ファイル path を指定して open: `with open('foo.txt', 'r') as f:`
      • with exp as x: とすると,exp の評価結果のオブジェクトが x に代入され,with ブロックを抜ける際に obj.__exit__() が実行され,よきにはからってくれる (ファイルの場合は close してくれる)
      • ファイル path を複数指定して cat したものを open: `import fileinput; f = fileinput.input(['foo.txt', 'baa.txt'])`
      • コマンドライン引数から与えたファイルの集合 (sys.argv[1:]) を cat したものを open: `import fileinput; f = fileinput.input()`
    • 読み込み (改行コードも取得される)
      • 1行ずつ読み込み: `f.readline()`
      • 1行ずつ読み込み: `for l in f`
      • 全ての行を読み込んで配列に確保: `arr = f.readlines()` (ファイルが小さいとわかっているとき以外非推奨)
    • 書き出し
      • 標準出力に書き出し(末尾に改行を挿入する): `print 'foo'`
      • 標準出力に書き出し(末尾に改行を挿入しない): `print 'foo',` (余計な空白も挿入されない)
      • 標準出力に書き出し(末尾に改行を挿入しない): `sys.stdout.write('foo')` (None を返す)
      • ファイルに書き出し(末尾に改行を挿入しない): `f.write('foo')`
      • ファイルに書き出し(末尾に改行を挿入する): `print >> f, 'foo'`
      • ファイルに書き出し(末尾に改行を挿入しない): `print >> f, 'foo',`

Tips (Shell)

  • <(command) で command の出力がファイル扱いになる
    • e.g., `$ diff <(./hoge) <(./fuga)`
    • cf. パイプでは標準出力→標準入力でしか渡せない (前処理側コマンドの出力を次処理側コマンドのコマンドライン引数として渡せない)
  • 特にシェル芸をしたい場合,OS X (BSD 系) のコマンド群を GNU/Linux 系の (ググった場合に大抵出てくる方の) コマンド群に置き換えるために,homebrew で gawk, gsed, gtar, coreutils (ls, cd などが含まれる) をまとめてインストール推奨

#03 2015/11/02(Mon) 13:00-14:30

参加者

  • 折田,横井,上村,ダワ
  • (TA) 山口,佐々木,高橋,鈴木

解いた問題

  • 005-008 (4問)

Tips

  • 利用しない変数はアンダースコアそのものないしアンダースコアからはじまる変数名を用いることが多い.
    • e.g. 回す回数にのみ興味があり,インデックスには興味がない for 文: `for _ in xrange(3): print('foo')`
    • `_` は ML 系のようにワイルドカードを表すわけではない.
  • 基本的な演算に対して,True は 1,False は 0 として振舞う.
    • http://docs.python.jp/2/reference/datamodel.html
      ブール型は整数のサブタイプで、ほとんどの演算コンテキストにおいてブール型値はそれぞれ 0 または 1 のように振舞います。
      ただし、文字列に変換されたときのみ、それぞれ文字列 "False" および "True" が返されます。
    • `[e0, e1][cond]`: 評価結果は三項演算子と等価.ゴルファーの定石らしい.ただし常に `e0, e1` がともに評価され無駄.文字数削減以外のメリットはない.
  • メソッドや関数を `()` を付けずに変数に代入すると,変数が呼び出し可能オブジェクトとなる.
    • e.g. `f='{}時の{}は{}'.format` `print f(12,'気温',22.4)'`
    • lambda 式のように扱える.
  • Python の `and`,`or` の挙動
    • `e1 or e2` は `e1` の評価結果が真(と見なせる)とき `e1` の 評価結果そのもの ,偽のとき `e2` の 評価結果そのもの を返す
      • `2 or 0` -> 2
      • cf. C言語: 評価を `e1` 止める点は同じだが,返すのは `e1` の(cond としての,bool としての)評価結果 \in {0, 1}
    • `e1 and e2` は `e1` の評価結果が偽(と見なせる)とき `e1` の 評価結果そのもの ,真のとき `e2` の 評価結果そのもの を返す
  • def の引数の可変長化
    • `*`ではじまるパラメータは可変長の引数を取り tuple として関数に取り込む
      • `def f(*args): print args; f(1,2,'foo')` -> (1,2,'foo')
    • `**` ではじまるパラメータは可変長の引数を取り dict として関数に取り込む
      • `def f(**args): print args; f(x=0,y=1)` -> {'x': 0, 'y': 1}
    • https://docs.python.org/2.7/reference/compound_stmts.html#function-definitions
  • 文字コード,unicode 型,str 型
    • `'文字列'` というバイト列 (エンコードはファイルやシェルのエンコード)は,評価されると,str 型(配列としてのバイト列)となる.
    • `u'文字列'` というバイト列 は、評価される unicode 型(len を取れたり,index で各「文字」が拾える配列)となる.
    • `codecs.encode(u, 'sjis')`: codecs.encode は unicode 型を受け取り,第2引数で指定した通りにエンコードした str 型を返す.
    • 「ソースコードに記載された実際のバイト列」と「今見えている文字列(バイト列をエディタやシェルのエンコーディングでデコードした,我々に見える文字列)」を区別する.
    • 「評価結果として返るデータ(unicode 型 or str 型)」と「今見えている文字列(データをエディタやシェルのエンコーディングでデコードした,我々に見える文字列)」を区別する.
    • 「今見えている文字列(ソースコードをエディタが解釈して表示された文字列)」と「そのソースコードが評価されるとどういうデータ型になるか」を区別する.
  • Pythonで日本語を扱う際の注意点

#02 2015/10/26(Mon) 13:00-14:45

参加者

  • 折田,横井,上村,ダワ,Diana
  • (TA) 佐々木,高橋,五十嵐,鈴木

解いた問題

  • 002-004

Tips

  • 文字列のクォーテーション
  • docstring
    • `"""` に続く1行目が関数の要約解説
    • 空行をひとつ挟んで,残りで詳細を書く
  • zip
    • 複数のシーケンスからタプルのリストを作る: zip(seq1 [, seq2 [...]]) -> [(seq1[0], seq2[0] ...), (...)]
    • 引数のシーケンス長が異なる場合は,一番短いものに合わせられる zip([1,2,3],[4,5]) -> [(1, 4), (2, 5)]
  • str.join の引数は,string が返ってくる iterable なオブジェクトならなんでも良い S.join(iterable) -> string
    • '_'.join('hoge') -> 'h_o_g_e'
    • ''.join( ('a', 'b', 'c') ) -> 'abc'
  • 文字列は immutable なので、`s += ...` の連発は、都度メモリ確保が発生して遅い&無駄.list に append → join にすべし.
    • → と思いきや誤差っぽい.(cf. JavaScript) 文字列長が極端に長ければ有用かもしれないが,どういうシチュエーション?
  • 計算量関連
    • set は x in s が早い (average: O(1))
      • set, dict は hash table が作られる.
      • set の要素および dict の key には hashable (≒immutable ?) なオブジェクトしか入れられない.
      • たとえば set の要素に list を入れることはできない.
    • list は(一般的なプログラミング言語で使う意味での)配列.連続したメモリ領域に書き込まれ,get が高速 (O(1))
    • (一般的なプログラミング言語で使う意味での)「リスト(cons cell 型のデータ構造)」を作りたければ,多重タプルで無理矢理実装できなくもない `(a, (b, (c, d)))`
    • TimeComplexity - Python Wiki
  • a, b, c は基本的に (a, b, c) の意 (syntax sugar?)
  • クラスのメソッドの第一引数に self をつけられるのは,クラスそのものの public method として呼び出した場合とインスタンスのメソッドを呼び出した場合の挙動を一致させたい(ないし一度に定義したい)という設計思想も入っている
    • `set.union(X,Y)` == `X.union(Y)` (第一引数が省略されている)
  • 文字列処理
    • str.split(): 任意のセパレータ文字列(初期値はスペース, タブ, 改行)で分割→リストに保存
    • 正規表現はスピードのボトルネックになるので極力使わない
      • `r'[]'` の中の「ピリオドにマッチ」を表す `.` はエスケープ不要
      • `[]` の中では先頭の `^` および先頭以外の `[`, `]`, `-` 以外はエスケープ不要
    • str.strip() 引数に入れた文字列を文字の集合と見て、文字列の両端に存在する該当文字を削除 '.,.ho..ge,,'.strip(',.') -> 'ho..ge'
      • 一方からだけ削りたい場合は rstlip, lstrip
      • 内側も削る場合は replace
  • 内包表記 (comprehensions)
    • dict comprehensions `{k:v for ...}`
  • generator
    • `(f(x) for x in iterable)` は generator expressions (ジェネレータ式)
    • generator は「遅延評価されるストリーム」の作成方法のひとつ
      • iterator はプロトコル.「next() メソッドを持ってね,こういう風に動作してね」というノリだけ定められている.
      • itertools.iterator という抽象クラスは用意されているが,実装上は独自型を作ってコンストラクタを充てることが多い?
      • docstring には↑を使う?
      • 「遅延評価されるストリーム」を作りたければ,1. iterator 的なクラスを作る,2. generator 式,3. generator 関数(def/yield)のいずれか
  • dictionary を value でソート: sorted(d.iteritems(), key=(lambda x: x[1]))
    • 全体としてリストを返す
    • iteritems(): (k,v) のリストの iterator を返す
  • fold, reduce
    • sum([('a','b'),('c','d')], ()) は,おそらく,`()`(空タプル)を初期値として `+` で left fold.
    • reduce は left fold.
    • reduce(func, seq, init) で init を与えない場合は,seq の 0 番目が init 扱いになり,func(seq[0], seq[1]) から計算がはじまる.

#01 2015/10/19(Mon) 14:40-17:00

参加者

  • 横井,上村,ダワ,Diana,ゼン
  • (TA) 山口,佐々木,高橋,五十嵐

Tutorial (佐々木)

  • 環境構築(environmental construction) slide(ja), slide(en)
    • 研究室の計算機環境,サーバへのログイン,Python の実行,virtualenv,Jupyter
    • (付録) tmux, linux コマンド
  • コードのアップロード方法(how to upload your source codes) slide(ja), slide(en)

解いた問題

  • 000, 001

Tips

  • インデントは4スペース (ソフトタブ)
    • エディタで Tab キーを押したときに '\t' ではなく半角スペース×4によるインデントが挿入されるように各自設定
  • 変数名関数名を,キーワードや組み込みの関数名とぶつけない
  • 組み込みのメソッドや関数の仕様の確認方法
    • Python 2.7.10 documentation を読む
      • 困ったことがあったらまず公式ドキュメントを確認
    • Dash for OS X (documentation をローカルで読む.有償ソフト.)
    • interactive shell (ipython) 上で `help(command)`, `command?` (e.g. `str.join?`)
    • Jupyter 上でメソッドにカーソルを合わせて Shift+Tab
  • `dir()` : module, class, object に紐づく attribute (プロパティ,メソッド) の一覧を表示
  • tuple は immutable
    • オブジェクト自体が mutable/immutable なことと,そのオブジェクトを入れた変数が再代入可能/不可能なことを混同しない.
      In [1]: a = (1,2)
      In [2]: b = (3,4)
      In [3]: c = a
      In [4]: a += b # a に新しいオブジェクト (1,2)+(3,4) = (1,2,3,4) を再代入
      In [5]: a
      Out[5]: (1, 2, 3, 4)
      In [6]: c
      Out[6]: (1, 2) # c が指すメモリ領域は [1] で確保されたもの
  • enumerate(): list を添え字付きで走査するときに便利
  • range はリストそのもの, xrange はイテレータ (のようなもの, xrange 型オブジェクト) を返す.
    • リストそのものが欲しい場合以外, xrange を使えば良い.
    • 3系では range の挙動が 2系の xrange と同様?
  • 代入は文. 式ではない. (値を返さない)
    • `y = x = 1` は valid だが, C言語のように 右結合的に順に評価 (`y = (x = 1)`) しているわけではなく, `y = x = a` という気泡が用意されている (実際, Python で `y = (x = 1)` はエラーする)
    • なお比較演算子も同様の記法がサポートされている e.g. `0 < x < 5` (これは `0 < x and x < 5` と等価. ただし `x` の評価回数で損)
  • ソースファイルのエンコード宣言 (マジックコメント?): `# -*- coding: utf-8 -*-`
    • `-*-` をつけておくと Emacs フレンドリー?
  • ドキュメンテーション文字列 (docstring) は reStructuredText 形式で書く

過去の記録


© Inui-Suzuki Laboratory 2010-2018 All rights reserved.
Recent Changes
2020-06-25 2020-06-17 2020-06-16 2020-06-10 2020-06-08 2020-06-01 2020-04-10 2020-04-02 2020-02-22 2019-06-07 2019-06-06 2019-05-23 2019-04-19 2019-04-08 2019-04-07 2019-04-03 2019-04-01 2019-03-08 2019-03-07 2019-03-01 2019-02-28 2019-02-15 2019-02-14 2019-02-13 2019-02-12 2019-02-08 2019-02-07 2019-02-06 2019-02-05 2019-02-04 2019-02-01 2019-01-31 2019-01-30 2019-01-29 2019-01-28 2019-01-26 2019-01-25 2019-01-24 2019-01-23 2019-01-22 2019-01-19 2019-01-18 2019-01-17 2019-01-16 2019-01-15 2019-01-10 2019-01-09 2019-01-08 2019-01-07 2019-01-06 2019-01-04 2019-01-03 2018-12-27 2018-12-26 2018-12-25 2018-12-21 2018-12-20 2018-12-19 2018-12-18 2018-12-17 2018-12-16 2018-12-13 2018-12-12 2018-12-11 2018-12-10 2018-12-07 2018-12-06 2018-12-05 2018-12-04 2018-12-03 2018-12-02 2018-11-29 2018-11-28