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

8.1. 構文エラー~9.2. Pythonのスコープと名前空間 をやった。

  • 例外のcatchはtry, exceptでやる。else節に例外が発生しなかったときの処理が書け、finally節にクリーンアップ処理を書く。
  • except ValueError: などのように、例外のクラスを指定できる。
  • except Exception as err: のようにすると、err.argsがExceptionのコンストラクタに指定した引数であり、その引数にアクセスできる
  • ユーザ定義例外を作るには、Exceptionクラスを継承したクラスを書けばよい
  • 関数内で関数が定義できる
  • 変数宣言に変数のスコープを表すキーワード nonlocal, globalが書ける
  • nonlocal指定の変数は最内スコープの1つ外側の変数を表す
  • global指定の変数はモジュールのスコープの変数を表す

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

6.1.2. モジュール検索パス~7.2.2. jsonによる構造化されたデータの保存 をやった。

  • パッケージはディレクトリ、モジュールは.pyファイル
  • パッケージのディレクトリには、__init__.pyを置く(空でもよい)
  • ファイル入出力のモードには以下がある

"r", "rb", "r+", "rb+", "w", "wb", "w+", "wb+", "a", "ab","a+", "ab+"

f = open('test.txt', 'r')
for line in f:
    print(line, end=' ')
f.close()

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回しか評価されなくて、リストや辞書などのイミュータブルなデフォルト引数は、関数呼び出しごとに変化してしまう。