いろいろ備忘録日記

主に .NET とか Java とか Python絡みのメモを公開しています。

Pythonメモ-60 (Pythonチュートリアルを読んで勉強になったこと) (python, tutorial, document)

概要

知り合いから、pythonチュートリアルの書籍版をもらいまして、読んでみたら結構勉強になったことがありました。

Pythonチュートリアル 第3版

Pythonチュートリアル 第3版

私が読んだのは、第三版。pythonのバージョンは3.5のものです。

ネットで公開されている公式のチュートリアルはさらっと読んだつもりだったのですが

やっぱり書籍で読むのもいいですね。

ソースの頭に coding: xxxx 書かなくていい

前にpythonちょこっと使っていたときは、まだバージョンが2の最初あたりだったので

ソースの先頭に

# -*- coding: utf-8 -*-

# coding: utf-8

って記述するのがクセになっていました。python3からはいらなかったんですね。

トリプルクォート文字列書くときのtips

"""で囲んだ文字列は複数行に渡って書くことができます。docstringとかでおなじみのもの。

行末文字も自動的に文字列に付与されるので、たとえば

def dodemoii_kansu(x, y):
    """
    どうでもいい関数

    :param int x: x
    :param int y: y
    :return: なし
    """


if __name__ == '__main__':
    print(dodemoii_kansu.__doc__)

というのを実行すると

$ python tekito.py 

    どうでもいい関数

    :param int x: x
    :param int y: y
    :return: なし

という風に、最初の一行目に空行がはいってしまいます。 なので、

def dodemoii_kansu(x, y):
    """どうでもいい関数

    :param int x: x
    :param int y: y
    :return: なし
    """

って書いてたのですが、よく考えると以下でいいのね。

def dodemoii_kansu(x, y):
    """\
    どうでもいい関数

    :param int x: x
    :param int y: y
    :return: なし
    """

こうすると、最初の行が継続してることになるので、変な空行入らない。

よくよく考えるとその通りですね。

例外の再送出

これはいつも忘れてしまうので、ついでにメモ。

例外をキャッチした後、そのまま再送出するには

    try:
        raise NameError('hello')
    except NameError:
        print('例外でた')
        raise  # 再送出

と、raiseのみ記述する。

9.2. Python のスコープと名前空間はMUST READ

9. クラス — Python 3.6.3 ドキュメント

めっちゃ勉強になりました。この章は絶対読んでおいた方がよいです。

global, nonlocalを使う場合はここの内容が理解できていないとバグりますね。

  • 名前空間とは、名前とオブジェクトのマッピングのこと。
  • 名前空間は様々なタイミングで作られ、寿命も様々。
  • ビルドイン名の入った名前空間は、インタープリタの起動とともに作られて、終了まで削除されない。
  • モジュールのグローバル名前空間は、モジュール定義の読み込み時に作られる。
  • 関数のローカル名前空間は、関数がコールされたときに作られて、関数からリターンしたり、関数内で処理されない例外を送出したときに削除される。
  • スコープとは、ある名前空間から直接アクセスできる、範囲のこと。
  • スコープは静的に生成されるが、利用は動的に行われる。
  • スコープは以下のように処理される。
    • 最初に検索されるのは、最も内側にあるローカル名の入ったスコープ
    • これを取り囲む関数がある場合、その名前空間の最も内側のスコープから順に検索される。ここには非ローカルと非グローバルが入っている。
    • 最後から2番目に検索されるスコープには、今いるモジュールのグローバルな名前が入っている。
    • 最後に検索されるのは、最も外側のスコープで、ビルドイン名が入った名前空間。

reprlib

実は知りませんでした。。。便利ですねこれ。

    import reprlib
    chars = set('jeijejfnasdouweoefbaefaeugb4epfuabbn')
    print(reprlib.repr(chars))

実行すると

{'4', 'a', 'b', 'd', 'e', 'f', ...}

結果が長い場合は適当なところでちぎって、残りを・・・にしてくれます。

Traceback (most recent call last) の意味

これは、書籍の「付録E」に載っていた内容なのですが、なるほどって思いました。

見慣れているので、なんとも思ってなかったです。そういえば、パっと見意味わからないですよね。

新しい呼び出し(つまり直近の呼び出し)ほど、後ろにあるよ。

って意味。なので、例外のトレースは、下から直近の呼び出しになるので

一番下の呼び出しが、最も直近の呼び出し。

付録F がとてもわかり易かった

これは書籍版にしか無いのかもしれませんが、付録Fは、普段はpython3使っている人が

いろいろな理由により、python2でスクリプトを書かないと行けない場合の注意事項について

記述されています。(たとえば、printがpython2では関数じゃないよとか)

例外の文法が異なるとか。

python3では、

raise 例外(引数)

なのが、python2は3種類も書き方がある。

raise 例外, 引数  # (1)
raise 例外(引数)  # (2)
raise 例外, 引数, トレースバックオブジェクト  # (3)

except の書き方も python3 は

except 例外:  # (1)
except 例外 as e  # (2)
except (例外1, 例外2):  # (3)

なのですが、違いがあるのは (2) の 例外オブジェクトを変数にバインドする方法

これが、python2ではカンマなので

except 例外1, 例外2:

ってやっちゃうと本来は例外2つキャッチしたかったのに例外1の変数として例外2が使われてしまう。

なるほど。。。これはたまにやってしまいそう。。。


過去の記事については、以下のページからご参照下さい。

サンプルコードは、以下の場所で公開しています。