ベスパリブ

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

pathlibのファイル操作いろいろ

pathlibとは

Python 3.4以上で推奨されているファイル・パス操作のモジュール。 os.path の代替となるモジュール。

docs.python.org

使い方をよく忘れるので備忘録です。

返り値はPathオブジェクトなので、文字列に変換したかったらstr()で囲んでやります。

カレントファイルの絶対パス

from pathlib import Path
this_file = Path(__file__).resolve()
print(str(this_file))
# C:\Users\XXXX\workspace\project\hoge.py

ディレクトリの取得

this_file.parents[0]
# C:\Users\XXXX\workspace\project

this_file.parents[1]
# C:\Users\XXXX\workspace\

パス結合

PROJECT_HOME = this_file.parents[0]
Path(PROJECT_HOME).joinpath("aaa", "bbb", "ccc", "ddd")
# C:\Users\XXXX\workspace\project\aaa\bbb\ccc\ddd

特定ディレクトリ下のファイルの検索

以下のようなフォルダ構成になっているとする

project  +--- aaa
               L aaa.txt
         + --- bbb
               L bbb.txt
         + --- ccc
               L ccc.txt
         + --- README.txt
folders = Path(PROJECT_HOME).glob("*")
for folder in folders:
    print(folder)
"""
WindowsPath('C:/Users/XXXX/workspace/project/aaa')
WindowsPath('C:/Users/XXXX/workspace/project/bbb')
WindowsPath('C:/Users/XXXX/workspace/project/ccc')
WindowsPath('C:/Users/XXXX/workspace/project/README.txt')
"""
folders = Path(PROJECT_HOME).glob("*")
for folder in folders:
    # フォルダでないならスキップ
    if not folder.is_dir():
        continue
    print(folder)
"""
WindowsPath('C:/Users/XXXX/workspace/project/aaa')
WindowsPath('C:/Users/XXXX/workspace/project/bbb')
WindowsPath('C:/Users/XXXX/workspace/project/ccc')
"""

特定ディレクトリ下のファイルの再帰的な検索

files = Path(PROJECT_HOME).rglob("*.txt")
for f in files:
    print(f)
"""
WindowsPath('C:/Users/XXXX/workspace/project/aaa/aaa.txt')
WindowsPath('C:/Users/XXXX/workspace/project/bbb/bbb.txt')
WindowsPath('C:/Users/XXXX/workspace/project/ccc/ccc.txt')
WindowsPath('C:/Users/XXXX/workspace/project/README.txt')
"""

ファイルの削除

files = Path(PROJECT_HOME).rglob("*.txt")
for f in files:
    f.unlink()

フォルダの削除

for folder in folders:
    # フォルダを削除する
    folder.rmdir()

フォルダの中身が空じゃない場合、エラーが発生するので注意。

フォルダの中身があっても削除したい場合は、shutil.rmtree()を使ったほうが良い。

import shutil

for folder in folders:
    # フォルダが空じゃなくても削除する(folderも削除される)
    shutil.rmtree(folder)

Pythonでダイクストラ法

編集履歴

(2021/02/21)ダイクストラのプライオリティキューが最短距離の小さい順に取り出されるようになっていなかったので、それを修正

ダイクストラ法とは

ダイクストラ法とは、「重み付きグラフにおける単一始点最短路アルゴリズム

つまり、「始点s から各頂点i までの最短コストを求める」アルゴリズム

使用条件は以下の通り。

  • 負のコストがないこと
  • 有向グラフ、無向グラフともにOK

ベルマンフォード法より高速なので、負のコストがないならばこちらを使うと良い。

ダイクストラ法の処理の流れは以下のサイトが詳しいです。

algorithmalgorithm

実装と使い方

蟻本に書いてあるとおりのプライオリティキューを使った実装です。

辺の数をE、頂点の数をVとすると、計算量は O( E \log(V) )

参考URL

Pythonの辞書(dict)のgetメソッドの速度を調べてみた

辞書(dict)でキーの存在確認をする際の方法としては、

  • in演算子を使いif文で条件分岐する
  • get()メソッドを使う
  • try exceptを使う(そんな人いるか?)

の3種類くらいだと思います。

その中でもget()メソッドはワンライナーで書けて便利なのですが、速度的にはどうなのだろうと気になったのでそれぞれ速度を比較してみました。

プログラム

gist.github.com

結果

  • in_operator1は、in演算子を使い、必ずアクセス成功する処理
  • in_operator2は、in演算子を使い、必ずKeyErrorする処理
  • try_except1は、try exceptを使い、必ずアクセス成功する処理
  • try_except2は、try exceptを使い、必ずKeyErrorする処理
  • get_method1は、get()メソッドを使い、必ずアクセス成功する処理
  • get_method2は、get()メソッドを使い、必ずKeyErrorする処理

時間は小数点第4位まで(5位以下切り捨て)

最速 /最遅

in_operator1 in_operator2 try_except1 try_except2 get_method1 get_method2
N=105 0.0079 0.0039 0.0049 0.0159 0.0109 0.0079
N=106 0.0678 0.0339 0.0458 0.1586 0.1019 0.0799
N= 107 0.6907 0.5215 0.4607 1.8228 1.0414 0.9741
N=108 8.0925 3.4299 4.6398 16.1180 10.2179 8.0003

考察

  • try exceptのexcept処理は遅い
  • get()メソッドは早くない
  • 速度を求めるならin演算子でif文が良い

参考URL

Python dict型でgetメソッドを使おう。(KeyError対策) | DevelopersIO

Pythonのin演算子の計算量について

リスト(list)、タプル(tuple)、集合(set)、辞書(dict)にはin演算子がありますが、それぞれ計算量が違うようです。

python リスト、辞書、セット型のinを使った時の参照速度を調べてみた。 - Qiita

Python Speed - www.peignot.net

リスト(list) タプル(tuple) 集合(set) 辞書(dict)
O(N) O(N) O(1) O(1)

今まではin演算子は全部O(N)かと思っていました。

なのでforループの中にin演算子を書いたら計算量がO(NM)とかになっちゃうのが嫌で使用を避けていたのですが、集合と辞書にはin演算子使っても良さそうです。

Pythonでベルマンフォード法

ベルマンフォード法とは

蟻本によれば、「重み付き有向グラフにおける単一始点最短路アルゴリズム

つまり、「始点s から各頂点i までの最短コストを求める」アルゴリズムです。

以下の条件で使えます。

  • DAG(有向グラフで閉路を持たない)である
  • 負のコストがあってもOK

すべての辺のコストが非負の場合、ダイクストラ法を使ったほうが高速に最短路が求まります。

実装と使用例

辺の数を E、頂点の数を Vとすると、計算量は O( EV )

実行結果

---sample1---
bf.exist_negatve_loop(): False
path: [0, 5, 3, 5, 4, 7]
---sample2---
bf.exist_negatve_loop(): True
---sample3---
bf.exist_negatve_loop(): True

参考URL

ベルマンフォード法の動きは、以下のリンク先が詳しいです。

Algorithm

行き詰まったり、やる気が起きないときの対処法

今の所の個人的なベストプラクティス

  • 行き詰まっているとき

  • やる気が起きないとき

    • さっさと家を出る(家にいる場合、最優先でこれをすること。家以外の施設で作業する)
    • 発声練習する
    • 体を動かす(ストレッチ・筋トレ)
    • 席を立つ(コンビニに行く)
    • アプリケーションをすべて閉じる

効果があるかもしれないと思っているもの

  • 何か書く

    • 今何しているか、何をしようとしているか、何に行き詰まっているかをノートに書き下す
    • お絵かきをしてみる
    • boogie board で思うままにラクガキ
  • 発声練習する

  • 席を立つ

    • コーヒーを淹れる
    • ストレッチ・筋トレをする
    • コンビニに行く
    • 廊下をうろうろしながら考える
  • アプリケーションをすべて閉じる

    • ブラウザのすべてのタブを閉じてみる
    • エディタを閉じてみる
    • Windowsのデスクトップ背景を眺める
    • PCをシャットダウンする
      • 一度シャットダウンする
      • 席を立つ(どっか行く)
      • 戻ってきてPCの電源を入れる
      • 最初からやり直してみる
  • 場所を変える

    • 家にいるなら、家を出る
      • 基本的に家で作業できるとは思わないこと
      • マック、スタバ、カラオケ、ビジネスホテル など
        • 車でしかいけないようなマックがgood

試したけど効果があるかわからなかったもの

  • アニメに話しかけてみる

    • 発声練習の一環
    • NEW GAME!を視聴しながら、ツッコミを入れる
      • 「なんでだよw」「走ると転ぶぞ」「怪我は大丈夫か」「俺もそう思ってた」「俺はあおっちに賛成」
      • 楽しくはあったが、何か解決策が湧いたりするわけではなかった
      • 気分転換にはなったか?
      • ついつい次の話を観てしまう
      • Amazon Primeを開いた時点で余計な情報が目に映って、そっちに興味を持っていかれる
  • そろばんアプリをしてみる

    • 頭の体操
    • ちょうどいい達成感と疲労感が残った
  • アルコール駆動開発

    • まったくうまくいかない
    • 眠くなる
  • 音楽・ラジオを聴きながら作業

    • 考えながらやるときはNG
    • 「あとはやるだけ」のときはまあOK