isatoの活動日記

管理人isatoが毎日の生活で気になったこと、勉強になったことを書いています。

Python3 モジュール化 (相対パスに注意)

pythonに関わらず、アプリを開発しているときに独自のモジュールを作ることはよくあると思います。

そこで注意するべき点について紹介します。

ファイル構造をこのようにします。

work/
  |--mymodule.py
  `--call.py

各ファイルを次のように編集します。

def greet():
    print("hello")
from mymodule import greet

def call():
    greet()

if __name__ == "__main__":
    call()

call.pyを実行すると、

$ python3 call.py
hello

となります。

では、さらに上の階層から、call.pyを呼び出す場合を考えましょう。

top/
  |--main.py
  `--work/
        |--mymodule.py
        `--call.py
from work.call import call
call()
$ python3 main.py
Traceback (most recent call last):
  File "main.py", line 1, in <module>
    from work.call import call
  File "~/top/work/call.py", line 1, in <module>
    from mymodule import greet
ModuleNotFoundError: No module named 'mymodule'

このように実行に失敗します。

なぜこうなったか

pythonではプログラムを実行すると、実行されたディレクトリ + sys.pathに保存されたパス の中から名前解決を行おうとします。

一つ目の例では、実行されたディレクトリ(work)内にmymodule.pyがあったため、問題なく実行できました。 しかし、二つ目の例では実行されたディレクトリ(top)内にmymodule.pyがなく、sys.pathにもworkディレクトリが登録されていなかったため、実行できませんでした。

これを動作させるためには、workディレクトリをsys.pathに登録すればよいです。

import sys
sys.path.append("work/")
from work.call import call
call()
$ python3 main.py
hello
これで実行できました。

ただ、このようなファイル構造よりも、次のようにすると使いやすいかもしれません。

    1. 予め独自モジュールを置いておくディレクトリAを作成しておく。
    2. ディレクトリAをsys.pathに登録しておく。
    3. 独自モジュールはディレクトリAに保存するようにする。

以上です。

オイラーの素数生成多項式の約数

オイラー素数生成多項式 \displaystyle{
x^ 2 + x + 41
}の約数について考えてみます。

愚直に \displaystyle{
x
}自然数を代入していき,約数を調べてみました。


すると,面白いことがわかります。

\displaystyle{
x^ 2 + x + 41
}という形で書ける数が順番に出てくるのです。


しかし,全てではありません。

\displaystyle{
x=244
}のとき, \displaystyle{
x^ 2 + x + 41 = 59821 = 163×367
}となり,

\displaystyle{
163
}\displaystyle{
367
}\displaystyle{
x^ 2 + x + 41
}という形で表現することができません。


\displaystyle{
x>244
}では,同様に表現できない数がたびたび現れます。

これらの数について調べたところ, \displaystyle{
x^ 2 + xy + 41y^ 2
} という形なら表現できることがわかりました。


今のところ反例は見つかっていません。

とても美しいです。

【数学用語】単数

最近,数論を独学で勉強していますが,用語が難しいですね。

少しづつ理解していきたいと思います。

数学用語の単数とは,実数の世界における{\displaystyle \pm{1}}のことのようです。

つまり,単数は乗算しても被乗算数の大きさを変化させない数と言えると思います。

代数的整数論において非常に重要な概念らしいのでメモしておきます。

ペル方程式

x2-dy2=1 という形で書ける方程式をペル方程式と呼びます。

(x,y) = (1,0)は自明な解となっていますが,ペル方程式には非自明な解が存在することが保証されています。

この方程式の一つの解{\displaystyle (x_0,y_0)}を見つけたとしましょう。 ここで,

{\displaystyle x_0+y_0\sqrt{d}}

という数を考えます。

この数を2乗してみます。

{\displaystyle
{(x_0+y_0 \sqrt{d})}^2 = {x_0}^2+{y_0}^2d+2 x_0 y_0\sqrt{d}
}

ここで得られる,{({x_0}^2+{y_0}^2d, 2 x_0 y_0)} もペル方程式の解になるらしいです。

代入して調べてみると確かにそうなっています。

つまり,一つの解が分かれば連鎖的に他の解も求まるということ。

とても面白い。

平方根は3つで1セット??

平方根について気になり色々調べていたところ,以下のような事実に気づきました。

{
a,b,c \in \mathbb{R} \\
\begin{eqnarray*}
    A &:=& abc\\
    B &:=& a+b+c\\
    C &:=& ab+bc+ca\\
\end{eqnarray*}
\\とすると, \\
\sqrt{a}+\sqrt{b}+\sqrt{c} = \sqrt{A^0B+2\sqrt{A^0C+2\sqrt{A^1B+2\sqrt{A^2C+2\sqrt{A^5B+2\sqrt{A^{10}C}}}}}}\ \ \cdots\cdots
}

この数式は,「三つの平方根の和が調和のとれた美しい形で表現される」ということを表しています。

また,Aのべき数として現れる数列は,リヒテンベルグ数列と呼ばれているようです。

A000975 - OEIS

さらに,立方根については二つの和で同様の現象が起こることがわかりました。

何か面白いことにつながっている気がします。

math.stackexchange.com

python3 文字列操作:分割

python3での文字列の分割にはsplit関数を使います。 使い方は以下の通りです。

string = "abc.def.ghi"

splist = string.split(".")

print(splist)

# => ['abc', 'def', 'ghi']


split関数の引数に分割文字を指定することで、文字列を分割することができます。 結構使えますので、覚えておきたいですね。

python3 アノテーションについて

アノテーションとは要は注釈のことです。

コメントでつけてもいいんですが、関数の引数と戻り値に関しては正式な書き方があるので、そちらを使ったほうが良いでしょう。

以下のように使います。

def multi(x :int , y :int) -> str:
    return f'{x*y}'


このようにすることで、一目で入出力が分かりますね!

可読性を高めるためにも積極的に使っていきましょう〜