D2MatE拠点メンバー及び関係者には、Webexメッセージにプログラミング等の質問サイト
"東工大MDX-PYTHON質問箱” が用意されています。
pythonやプログラミングに限らず、回答できる質問には対応し、必要に応じてこのページで公開します。
下記tipsのいくつかは、tklib (tkApplication、tkFit、tkFit_m、tkPlotEvent など) に実装されています
以下の資料が含まれています
モジュールを単独で実行する場合だけ特定の関数を呼び出すには、__name__
変数を利用します。
モジュールプログラムから実行した場合は __name__ に
"__main__" が入りますが、他のプログラムから import
された場合は、そのモジュール名が入ります。
そのため、以下の構文により、モジュールが単独で実行された時だけ
main() 関数を呼び出すことができます。
モジュールの場合、main()
関数にモジュール関数・クラスのテストプログラムを書いておくと便利です。
void main():
...
if __name__ == "__main__":
main()
解決方法: signalモジュールの signal.signal() 関数で handler関数を設定する
注: scipy.optimizeでは、ライブラリ内で割り込み設定をしている様子。使えない
import signal
class tkStopHandler():
def __init__(self):
self.stop_flag = False
def __call__(self, signal, frame):
while 1:
print("")
print("Type 'yes' if terminates the program>> ", end = '')
keyin = input()
if keyin == 'yes':
print(" Stopping")
self.stop_flag = True
return True
else:
print(" Cancelled")
break
return True
stop_hander = tkStopHandler()
signal.signal(signal.SIGINT, stop_hander)
# ctrl-cの割り込みテスト: ここまで
#while(True):
# if stop_hander.stop_flag:
# exit(0)
matplotlibはpythonの標準的なグラフ作成モジュールです。matplotlibのwindowでは、Tk
のイベントを使ってインタラクティブなプログラムを作ることができます。
グラフ中のデータ点をクリックした際に、データ情報をコンソールに表示する疑似コードを以下に示します。
# x, y にデータのリストを入れて、グラフを描画します
fig = plt.figure()
ax1 = fig.add_subplot(1, 1, 1)
ax1.plot(x, y)
# グラフを表示しますが、plt.show()
を使うとプログラムが停止してしまうため、plt.pause()
を使います。
# グラフは再描画されますが、プログラムは継続します
plt.pause(0.1)
# データの集合 (xlist, ylist) のうちから、データ (x,y)
に一番近いindexを探して返します。
def find_nearest_data(x, y, xlist, ylist):
minr2 = 1.0e300
ihit = None
for i in range(len(xlist)):
xi = xlist[i]
yi = ylist[i]
r2 = (x - xi)**2 + (y - yi)**2
if minr2 > r2:
minr2 = r2
ihit = i
return ihit, minr2
#
マウスの左ボタンがクリックされたときに呼び出されます。
def onclick(event):
# event.inaxesに、クリックされた位置が含まれる axis
変数が返されます。
# ax1 内でクリックされた場合だけ次の処理をします。
if event.inaxes != ax1:
return
# (event.xdata, event.ydata)に、ax1に対応する (x, y) の値が入っています
# データの集合 (x, y) のうちから、データ (xe, ye)
に一番近いindexを取得します
idx, r2 = find_nearest_data(event.xdata, event.ydata, x, y)
print("")
# クリックした点に一番近いデータ (x[idx], y[idx])
をコンソールに表示します。
print(f"clicked at idx = {idx}: x = {x[idx]} y = {y[idx]}")
# マウスの左ボタンクリックイベント button_press_event を
onclick() に紐づけます (bind)
fig.canvas.mpl_connect("button_press_event", onclick)
# plt.pause()を使うとプログラムが最後まで進行してしまうので、input()
関数を呼ぶことで、
# ENTERを入力するまでプログラムの終了を待ち状態にします
print("")
print("Press ENTER to terminate")
input()
注: pythonの長所はあくまでも、プログラムを簡単に作成、実行できる点です。
さまざまな工夫を使って高速化する必要がある場合は、コンパイル言語を使って実装しなおすほうが良いこともあります
pythonは基本的にインタプリタ型言語であり、実行時にテキストのソースプログラムを機械語に翻訳しながら実行します。
また、オブジェクト指向言語であり、全ての関数、変数はオブジェクトとして扱われます。多くのスクリプト言語
(あるいは Light Weight Language: LWL) と同様、
pythonのオブジェクトは辞書型変数 (__dict__)
が実体です。そのため、オブジェクトのattributeへのアクセスは非常にオーバーヘッドが大きくなります。
それに対し、C/C++で実装されている組み込み構文・関数やモジュールの実行速度は格段に速くなります。以下の注意を払うことで
pythonプログラムの高速化ができるかもしれません。
ただし、上記のような工夫
(C/C++などで書き直すことを除く)
をしたとしても、実行速度はコンパイル言語にはまったくかないません。
スクリプト言語と比較しても、例えば、オブジェクトを使わないperlと比べても数分の1の速度になります
(perlでオブジェクト変数アクセスを主にするとpythonと同程度まで遅くなります)。
注: pythonのコードをバイトコンパイルすこともできます。ただし、オブジェクトにattributeを動的に追加したり、eval()
を使うコードには事前コンパイルは機能しません。
参考: Pythonのコードをバイトコンパイルする方法
注: pythonのバージョンアップによって実行速度が改善されていることがあります。
注: python3.13から Just in time コンパイラの実装が始まりました。まだ十分な性能は出ていないようですが、将来的には高速化される可能性があります。
注: pythonと言語互換性が高いMojoを使うことも、高速化のための現実的なオプションです