Python3.6.3チュートリアル写経20171113

5.5. 辞書型~6.1.1. モジュールをスクリプトとして実行する をやった。 以下メモ。

  • 辞書のキーにできるのは、イミュータブルな型だけ。すなわち、文字列、数値、タプル。
  • dict(ペアのリスト) (ペアのリスト->辞書)の逆は my_dict.items() (辞書->ペアのリスト)
  • キーのリスト: list(my_dict.keys())
  • 値のリスト: list(my_dict.values())
In [1]: fruits = {'apple': 3, 'banana': 2, 'peach': 4}

In [2]: for k, v in fruits.items():
   ...:     print(k, v)
   ...:     
apple 3
banana 2
peach 4
  • シーケンスの生成の仕方

    • ソートされたシーケンス: sorted(シーケンス型)
    • 逆順にしたシーケンス: reversed(シーケンス型)
    • インデックス(0-origin)とのペアにされたシーケンス: enumerate(シーケンス型)
    • タプルにされたシーケンス: zip(シーケンス型, シーケンス型, ...)
    • 型変換: list(シーケンス型), set(シーケンス型), tuple(シーケンス型)
  • 論理演算子は、not, or, and

  • モジュールは、モジュール名.py というファイルに、関数を定義することで作成する
  • モジュールのインポートの仕方、「import モジュール名」と「from モジュール名 import シンボル名」
  • 前者は、インポート先のシンボルテーブルにモジュール名しか入らないため、モジュール名.関数名 で関数を参照する
  • 後者は、インポート先のシンボルテーブルにimportの後ろのシンボルが入るため、シンボルをモジュール名無しで参照できる。「import モジュール名 *」という書き方は可読性を低くするので非推奨
  • モジュールの最後にスクリプトとして実行するプログラムが書ける(実行コマンド: $ python fib.py 50)
def fib(n):
    """Write Fibonacci series up to n."""
    a, b = 0, 1
    while b < n:
        print(b, end=' ')
        a, b = b, a+b
    print()

def fib2(n):
    """Return Fibonacci series up to n."""
    result = []
    a, b = 0, 1
    while b < n:
        result.append(b)
        a, b = b, a+b
    return result

if __name__ == "__main__":
    import sys
    fib(int(sys.argv[1]))

Python3.6.3チュートリアル写経20171112

5.1.4. ネストしたリストの内包表記~5.4 集合型 をやった。 以下メモ。

  • ネストしたリストの内包表記を書くことができるが読みづらいので、zip関数を使った方がいい
In [1]: matrix = [
   ...:     [1, 2, 3, 4],
   ...:     [5, 6, 7, 8],
   ...:     [9, 10, 11, 12],
   ...: ]

In [3]: [[row[i] for row in matrix] for i in range(4)]
Out[3]: [[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]

In [7]: list(zip(*matrix))
Out[7]: [(1, 5, 9), (2, 6, 10), (3, 7, 11), (4, 8, 12)]

In [12]: [list(elm) for elm in list(zip(*matrix))]
Out[12]: [[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
  • シーケンス型には、list, tuple, rangeがある
  • シーケンス型と似たものに、テキストシーケンス型、バイナリシーケンス型がある
  • タプルはイミュータブル(そのため、タプルの要素への代入ができない)
  • 集合型というものがある(差集合: -, 和集合: |, 共通部分: &, EXOR: ^)

Python3.6.3チュートリアル写経20171111

4.7.6 ドキュメンテーション文字列~5.1.3 リストの内包表記 をやった。

以下メモ。

  • リストはappendとpopにより、スタック(LIFO)として使える
  • キュー(FIFO)としては、collectionsモジュールからdequeueをimportして以下のように使う
In [15]: from collections import deque

In [16]: queue = deque(["Eric", "John", "Michael"])

In [17]: queue
Out[17]: deque(['Eric', 'John', 'Michael'])

In [18]: queue.append("Terry")

In [19]: queue
Out[19]: deque(['Eric', 'John', 'Michael', 'Terry'])

In [20]: queue.append("Graham")

In [21]: queue
Out[21]: deque(['Eric', 'John', 'Michael', 'Terry', 'Graham'])

In [22]: queue.popleft()
Out[22]: 'Eric'

In [23]: queue
Out[23]: deque(['John', 'Michael', 'Terry', 'Graham'])

In [24]: queue.popleft()
Out[24]: 'John'

In [25]: queue
Out[25]: deque(['Michael', 'Terry', 'Graham'])
  • リスト内包表記では、mapやfilterが表現できる(mapは先頭の式で表し、filterはforの後ろのifで表す)
  • 数学的には、以下のIn [44]のように書けるとうれしいが、inの後ろに定義されていない変数を書くことはできない
In [42]: vec = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

In [43]: [num for elem in vec for num in elem]
Out[43]: [1, 2, 3, 4, 5, 6, 7, 8, 9]

In [44]: [num for num in elem for elem in vec]
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-44-805eb91a5d03> in <module>()
----> 1 [num for num in elem for elem in vec]

NameError: name 'elem' is not defined

Python3.6.3チュートリアル写経20171106

4.7.2 キーワード引数~4.7.5 ラムダ式をやった。

以下メモ

  • 下記のような関数が書ける(argumentsは可変長引数、keywordsは可変長キーワード引数)
def cheeseshop(kind, *arguments, **keywords):
    print("-- Do you have any", kind, "?")
    print("-- I'm sorry, we're all out of", kind)
    for arg in arguments:
        print(arg)
    print("-" * 40)
    for kw in keywords:
        print(kw, ":", keywords[kw])
  • リストをアンパックして関数に引数として渡せる(アンパックとは、リストの要素を前から順番に、仮引数に渡すこと)
def person(name, age):
    print(name, 'is', age, 'years old.')

p = ['taro', 20]
person(*p) # アンパック
  • 辞書をアンパックして関数に引数として渡せる(このときは、キーワードを指定して引数をに値を渡していると考えられる)
def person(name, age):
    print(name, 'is', age, 'years old.')

p = {'name': 'taro', 'age': 20}
person(**p) # アンパック
# タプルのリストをタプルの2番目でソート
a = [(1, 'kuma'), (2, 'neko'), (3, 'inu')]
a.sort(key=lambda pair: pair[1])
a
[(3, 'inu'), (1, 'kuma'), (2, 'neko')]

Python3.6.3チュートリアル写経20171104

Python チュートリアル — Python 3.6.3 ドキュメントを写経してる。 4.7.1 デフォルトの引数値までやった。

以下メモ。

  • PythonのREPLはpythonよりもipythonの方が便利
  • for文にelse節があり、breakするとelse節は実行されない
  • 文字列はイミュータブル
  • リスト、辞書はミュータブル
  • 文字列はシングルクォート'で囲むか、ダブルクォート"で囲むか、ダブルクォート3つで囲む
  • 文字列をシングルクォートで囲むときには、ダブルクォートをエスケープする必要がなくなり、ダブルクォートで囲むときには、シングルクォートをエスケープする必要がなくなる
  • 文字列をダブルクォート3つで囲むとき、文字列内の改行がそのまま改行になる。また、"""に隣接しなければ、ダブルクォートをエスケープしなくても大丈夫っぽい
  • for文内でリストを変更するときには、「for x in my_list[:]:」のようにしてリストをコピーする必要あり
  • デフォルト引数は1回しか評価されなくて、リストや辞書などのイミュータブルなデフォルト引数は、関数呼び出しごとに変化してしまう。

ベイジアンネットワーク

身の回りでベイジアンネットワークなどの言葉をよく聞くようになった。 ベイジアンネットワークは、ビッグデータを解析して、ある現象が発生したときに、何が原因かを確率的に抽出する手法のようだ。

僕としては、このような手法に対して、本当にうまくいくのかな、と少し懐疑的だ。 原因を抽出するときに、プログラムは、おそらく、原因A1、原因A2、…、原因ANに対して、確率分布を出力するのだろう。 ところが、これらの原因の集合そのものは、人間があらかじめ用意してあげる必要があるのではないか。

また、この手法では、原因をノードとするネットワークを作るらしいのだが、ネットワーク構造を決めるアルゴリズムがあるらしい。

懐疑的でありつつも、わからないことばかりで、興味がわいてくる。