ベスパリブ

プログラミングを主とした日記・備忘録です。ベスパ持ってないです。

クラスの特殊メソッド__str__()とは

「クラスオブジェクトを文字列で返すメソッド」です

class Hoge():
    title = "this is Hoge."

    def __str__(self):
        return self.title

# クラスオブジェクトを表示すると
print(Hoge())  # this is Hoge.

# インスタンスでもOK
hoge = Hoge()
print(hoge)  # this is Hoge.

文字列でない場合、エラーが発生します。

class Hoge():
    title = "this is Hoge."

    def __str__(self):
        return 1  # 数値にすると...

print(Hoge())
""" 以下のようなエラーになる
Traceback (most recent call last):
  File "Main.py", line 7, in <module>
    print(Hoge())
TypeError: __str__ returned non-string (type int)
"""

Anacondaで仮想環境を構築してDjango環境を作る(Windows)

AnacondaはPythonの実行環境を複数構築することができます。 コマンドプロンプトにAnacondaのパスが通っているなら、以下のコマンドで環境を作成できます。

# conda create -n [環境名]
# pythonのバージョンを指定したい場合は conda create -n [環境名] python=3.6 など
> conda create -n py36 python=3.6

仮想環境の確認は以下のコマンド

> conda info -e

仮想環境の削除は以下のコマンド

> conda remove -n py37 --all

仮想環境の切り替えは以下のコマンド

# activate [環境名]
> activate py36

仮想環境から抜けるときは以下のコマンド

> deactivate

djangoのインストールをします。

> conda install django
# djangoのバージョンを指定したい場合は conda instal django==2.1 など

djangoのバージョン確認は、Pythonインタプリタを立ち上げて以下のコマンド

> python
>>> import django
>>> django.get_version()
'2.1'
>>> exit()

こんな感じです。 今までpyenv使ってましたけど、それより断然使いやすくて驚きました。

参考

Anaconda でよく使うコマンド一覧 - Qiita

ソフトマックス関数の式変形

ゼロから作るDeepLearningという本を読んでいるのですが、ソフトマックス関数でオーバーフローしないように式変形するときは次のように変形するとあります。

\displaystyle y_k = \frac{exp(a_k)} {\sum_{i=1}^n exp(a_i)}

\displaystyle = \frac{C exp(a_k)} {C \sum_{i=1}^n exp(a_i)}

\displaystyle = \frac{exp(a_k + log{C})} {\sum_{i=1}^n exp(a_i + log{C})}

\displaystyle = \frac{exp(a_k + C')} {\sum_{i=1}^n exp(a_i + C')}

のですが、2行目から3行目の変形で分子のところをC exp(a_k) = exp(a_k + log{C}) とやっているのですが、こんな公式あったっけ?と手が止まりました。 普通にありました(高校数学!)。

指数と対数の関係式

底をa(a>0)という条件で、\displaystyle x = a^{log_a{x}} が成り立つので、\displaystyle C = e^{log_e{C}}と変形できます。

よって、上記の2行目から3行目の分子の変形は、

 C exp(a_k) = exp(log_e{C}) exp(a_k)

 = exp(a_k + log{C})

ということですね。

Atomエディタのremote-ftpで"Sync local -> remote"をするとインジケータが固まるとき

"Sync local -> remote"をするとインジケータが固まってしまう現象が起きました。

これはおそらくパーミッションの問題で、アップロードしたいファイルに書き込み権限を付与していないせいで起きます。

固まった場合、一度Packagesメニュー > Remote FTP > disconnect で切断した後、再度接続し、ファイルのパーミッションを直したあとでSync local -> remoteするとうまくいきます。

という内容のissueを報告しましたけど、かなりissue溜まってるからレスポンスは当分後になりそう。自分でPRするのが一番いいんでしょうけど。

state machineの話(あるいはPython3での実装)

Statechart
このような記事を見つけました。
ステートマシン(state machine)実装のための本があることを初めて知りました。

ここで提案されている手法は、[* 状態変数を使うかわりに現在の状態を示す関数を使う]というものである。たとえば「あ」という状態は`あ()`という関数で表現し、「い」という状態は`い()`という関数で表現する。「あ」や「い」という状態の上位階層として「あ行」という状態が存在するので、それは`あ行()`のような関数で表現する。このように、[* あらゆる状態を関数として表現する]ところがミソである。

iPhoneフリック入力はこんな感じらしいです。はぇ~。

そういえば以前にPython3でstate machineを実装したことがあるので、そのときのやり方をメモって置きます。結構悩んで実装した記憶が…。

from enum import Enum

class StateMachine():
    class State(Enum):
        """ state machineの状態 """
        Start = 0 # 状態0(初期状態)
        S1    = 1 # 状態1
        S2    = 2 # 状態2
        S3    = 3 # 状態3
        S4    = 5 # 状態4

    def __init__(self):
        self.state = self.State.Start

    def update_state(self):
        """ state machineを更新する(状態遷移する) """

        if self.state is self.State.Start:
            """ 初期状態 """
            self.state = self.State.S1
            print("State: Start")
            return

        elif self.state is self.State.S1:
            """ 状態1 """
            self.state = self.State.S2
            print("State: S1")
            return

        elif self.state is self.State.S2:
            """ 状態2 """
            self.state = self.State.S3
            print("State: S2")
            return

        elif self.state is self.State.S3:
            """ 状態3 """
            self.state = self.State.S4
            print("State: S3")
            return

        elif self.state is self.State.S4:
            """ 状態4 """
            self.state = self.State.S1
            print("State: S4")
            return

実際に使うときは、ループを回して使います。

import time

if __name__ == "__main__":
    sm = StateMachine()
    while True:
        sm.update_state()
        time.sleep(1.0)

上記の実装の良いところを挙げると、
・state machineの実装がクラス内で完全に閉じている
・使うときはupdate_state()を呼び出すだけ
・引数を増やしやすい
・シンプル
くらいです。まあ特別なことはしていません。

実際に処理を実装するとわかるのですが、処理が長くなるとif文が長くなり可読性落ちるので、実際の処理はメソッド化するのが無難です。

if文の数が多くなると可読性が落ちたり、無駄な評価がされて遅いというデメリットが考えられるので、if文をディクショナリに書き換えればもっと良くなるかもしれません。試してないですけど。

あと、これはstate machineを実装する上で一般的に言える注意点だと思うのですが、状態を変更した後は(self.stateを変更した後は)すぐにreturnしなければいけません。さもなければ状態を追いかけることが難しくなります。以前、状態が変更された後も処理が続き、条件によってはさらに状態が上書きされ、そしてまた条件によっては上書きされ…というのが続き、最後にreturnされるstate machineを見たことがあるのですが(そしてそのプログラムのバグを追いかけていたのですが)、恐ろしくしんどいです。リーダブルコード7.5章にも書いてありますが、できることなら関数から早く返しましょう。

関数で複数のreturn文を使ってはいけないと思っている人がいる。アホくさ。

ちなみにPythonには既にstate machineを扱うライブラリがあるようです。独自実装で特殊なことする必要がなければこれを使うという手もあります。便利世の中~。
transitionsでステートマシンを扱う [Python]