Python のメモ
目次

いろいろ

ローカルに HTTP サーバーを立てる

http.server --- HTTP サーバ

# ポートを指定 (現在のディレクトリのファイルを提供)
$ python -m http.server 8000
# バインドするアドレスを指定 (現在のディレクトリのファイルを提供)
$ python -m http.server 8000 --bind 127.0.0.1
# ファイルを提供するディレクトリを指定
$ python -m http.server --directory /tmp/

ユーザー定義例外

8.5. ユーザー定義例外

  • Exception クラスを、直接または間接的に継承する

    • BaseException : 全ての組み込み例外の基底クラスです。ユーザ定義の例外に直接継承されることは意図されていません (継承には Exception を使ってください)。

  • 大抵は、いくつかの属性だけを提供し、例外が発生したときにハンドラがエラーに関する情報を取り出せるようにする程度にとどめる

  • だいたいは、標準の例外の名前付けと同様に、 "Error" で終わる名前で定義する

  • 複数の別個の例外を送出するようなモジュールを作成する際には、そのモジュールで定義されている例外の基底クラスを作成するのが一般的なプラクティス

interface 使いたい

抽象基底クラス

from abc import ABCMeta, abstractmethod


class Pushable(metaclass=ABCMeta):
    @abstractmethod
    def push(self, x):
        """何でも push"""

    @classmethod
    def __subclasshook__(cls, subclass):
        # これを実装しておくと、暗黙的にインターフェイスを実装しているインスタンスも
        # インターフェイスのインスタンスだと確認できる
        if cls is Pushable:
            if any('push' in B.__dict__ for B in subclass.__mro__):
                return True
        return NotImplemented


class HeyPushable(Pushable):
    def push(self, x):
        print(f'Hey {x} push.')


class HoyPushable(Pushable):
    def pull(self, x):
        print(f'Hoy {x} pull.')


class PoyPushable:
    def push(self, x):
        print(f'Poy {x} push.')


class NyaPushable:
    def pull(self, x):
        print(f'Nya {x} pull.')


class HeyHeyPushable(Pushable):
    def push(self, x, y):
        # 引数違いも互換性ありとみなされる
        # (PyCharm では警告出る)
        print(f'Hey hey {x}, {y} push.')
>>> hey = HeyPushable()
>>> isinstance(hey, Pushable)
True
>>> hey.push('husky')
Hey husky push.

>>> hoy = HoyPushable()
Traceback (most recent call last):
  File "<console>", line 1, in <module>
TypeError: Can't instantiate abstract class HoyPushable with abstract methods push

>>> poy = PoyPushable()
>>> isinstance(poy, Pushable)
True

>>> nya = NyaPushable()
>>> isinstance(nya, Pushable)
False

>>> heyhey = HeyHeyPushable()
>>> heyhey.push('husky', 'shiba')
Hey hey husky, shiba push.

defaultdict

リストの初期化が不要になる!

StringIO().seek(0)

https://docs.python.org/ja/3/library/io.html#io.IOBase.seek

  • 先頭にもどす、 (カーソルを先頭に戻すみたいなイメージ)

yield dict(zip(columns, data))

# これは、
for column, value in zip(columns, data):
    row_dict[column] = value
    yield row_dict

# こう書ける。
yield dict(zip(columns, data))
  • zip はタプルのイテレータを返す -> タプルから辞書を作れる

  • dict(iterable, **kwarg)

  • https://docs.python.org/ja/3/library/stdtypes.html#dict

    • それ以外の場合、位置引数は iterable オブジェクトでなければなりません。iterable のそれぞれの要素自身は、ちょうど 2 個のオブジェクトを持つイテラブルでなければなりません。それぞれの要素の最初のオブジェクトは新しい辞書のキーになり、2 番目のオブジェクトはそれに対応する値になります。同一のキーが 2 回以上現れた場合は、そのキーの最後の値が新しい辞書での対応する値になります。

if __name__ == "__main__"

http://blog.pyq.jp/entry/Python_kaiketsu_180207

  • Pythonでは、インポートされたファイルの中身は実行される

組み込み型と名前が被った場合

inint など、キーワード・組み込み型と同じ名前を変数名にしたい場合は、末尾に _ を付ける。

組み込み関数

isinstance(object, classinfo)

https://docs.python.org/ja/3/library/functions.html#isinstance

  • 継承を考慮してくれる

  • classinfo には複数指定できる (タプルで)

all(iterable)

all(iterable)

  • iterable の全ての要素が真ならば (もしくは iterable が空ならば) True を返す。

sorted(iterable, *, key=None, reverse=False)

sorted

  • タプル型 (tuple) : タプルはイミュータブルなシーケンス なので、 ソートできる。

# これは、
summary_list = list(summary_dict.values())
summary_list.sort(key=lambda x: x['sort_key'])

# ``sorted`` という関数を使って以下のように書ける。
summary_list = sorted(summary_dict.values(), key=lambda x: x['sort_key'])


# さらに、for文をこんなふうに書くと ``summary_list`` を作る工程が不要。
for _, summary in sorted(summary_dict.items()):
    # ....

@property

https://docs.python.org/ja/3/library/functions.html#property

  • @property デコレータ を付けると、プロパティのように呼び出せる。

  • 同じ名前のまま 読み出し専用属性の getter にしてくれる

    # 付けるとき
    @ property
    def husky(self):
        return self.access_datetime.strftime('%Y/%m/%d %H')
    
    # 呼び出すとき
    xxx.husky
    

正規表現

バックスラッシュ感染症

バックスラッシュ感染症

# こんなふうに書く
r"ab*"
  • r を文字列リテラルの先頭に書くことでバックスラッシュは特別扱いされなくなる

  • 多くの場合 Python コードの中の正規表現はこの raw string 記法を使って書かれる

re.MatchObject.groupdict

https://docs.python.org/ja/3/library/re.html#re.Match.groupdictgroupdict

  • マッチの、すべての 名前つきの サブグループを含む、サブグループ名でキー付けされた辞書を返す

  • リファレンスのサンプルコードを見ると一目瞭然なので、そちらを見てください

長い正規表現を記述する方法

Python2

unicode と str

3.1.3. Unicode 文字列

>>> # -*- coding: utf-8 -*-
>>> 'ふみ' == u'ふみ'
False
>>> 'fumi23' == u'fumi23'
True
>>>
  • python2 の場合、マルチバイトを含むと u の有無で違うオブジェクトとして判定される。

  • python2の文字には unicodestr がある。 ascii 文字しか含まない場合は 同じ値と判断されるけど基本的に別物として考えたほうがいい。

coding: utf-8

ソースコードの文字エンコーディングを指定する

# -*- coding: utf-8 -*-
  • ファイルの先頭に記述する

  • 記述しないと、 Python2 環境かつファイルにマルチバイトが含まれていると SyntaxError が発生する。

  • Python3 環境では不要