私が歌川です

@utgwkk が書いている

11月の体調まとめ

前回までの振り返り

utgwkk.hateblo.jp

寝てると首筋と肘が焼けるように熱くなり、痒くなる

  • 10月にはもう発症しなくなったと思う

utgwkk.hateblo.jp

肌荒れ

  • 継続中

目覚めの悪さ

  • 生活リズムはそこそこ修正できた
  • ただし油断して寝すぎることがあった

不安・緊張

  • ときどきある
    • 深夜急に悪くなることが多い
    • 金銭面の不安が増えた?

今月の振り返り

睡眠

  • 二度寝のしすぎがちらほらあった
    • 寒さのせいもありそう
    • 起きるタイミングで部屋を適温にする

  • 口を大きく開けると左奥歯のあたりが痛い
    • 虫歯?
    • 親知らず?

肌荒れ

  • 首筋もう落ちついてる
  • 手首まだ治ったり治らなかったりする
  • 頭がかゆい
    • フケ・かゆみ用シャンプーを買った

今月の健康活動

プランク

追記

野菜ジュース

  • 1日分の野菜350g
  • 1週間ぐらい飲んでる

シャンプー買い替え

  • 先述した通り
  • 今までは夏用のスースーするやつを使ってた
    • 肌によいということはなさそう
    • そもそも季節外れで寒い
  • ちょっと高いので効いてほしい

まとめ

皮膚科さすがにそろそろ行こう(歯科も?)

Git 管理されたファイルの履歴を書き換えて、全てのファイルをまるごと特定ディレクトリ内に移動させる

tl;dr

書き換えないと死ぬという状況でなければ git mv で済ませましょう (追記)

$ git filter-branch --tree-filter \ 
  'mkdir hoge; for file in `ls | grep -v hoge`; do mv -t hoge $file;

やりたいこと

Git リポジトリのルートディレクトリ以下のファイル/ディレクトリを全て hoge/ 以下に移動させたい

main.py
requirements.txt
module/
  __init__.py

hoge/
  main.py
  requirements.txt
  module/
    __init__.py

といった感じに移動したかった

最終的にやったこと

$ git filter-branch --tree-filter \ 
  'mkdir hoge; for file in `ls | grep -v hoge`; do mv -t hoge $file;

雑に mv * hoge/ とかだとできなかった

お気持ち

意味もなく履歴を書き換えまくろうとしない方が命のためです(追記)

メソッドに渡す引数に対するアレヤコレヤの前処理、たとえば引数の形式をメソッドで求められているものに揃えるとか、引数が正しいことをチェックするとか、こういったことは呼び出し側でするべきという風に思いつつある。

メソッドにはメソッドの役割があって、のりを越えた処理をしまくるとややこしくなると思っている。そういう風にインターフェースを整えていくべきだと思っていて、そうしようとするとメソッドを小分けにしていくことになるのではなかろうかと思っている。

副作用のある処理を小分けにするときもそれでよいのだろうか、とかも思うんだけど、そうこうしているうちに夜が更けつつある。

Ruby の dig メソッドが便利なので Python で実装した

dig メソッドとは

instance method Hash#dig (Ruby 2.6.0)

たとえば各種 API を叩いて返ってきた JSON をパースした後の辞書型のような、データがいくらでもネストしてあるようなデータ構造があるとき、普通なら obj['path']['to']['destination'][2] とか obj.path.to.destination[2] のようにしてアクセスしなければなりません。

この dig メソッドを使うと、先述したどちらの場合でも dig(obj, 'path', 'to', 'destination', 2) のような形式で要素にアクセスすることができます。また、該当する要素がない場合の挙動(例外か、それとも None を返す*1か)もメソッド側で制御することができます*2

残念ながらまだ存在する、データ構造を掘り進めた先にあるものが辞書型なのかオブジェクトなのか分からないようなインターフェース、それを気にせずに我々は掘り進めるだけでよいというのが、この dig の実装のポイントです。

実装

def dig(obj, *keys, error=True):
    keys = list(keys)
    if isinstance(keys[0], list):
        return dig(obj, *keys[0], error=error)

    if isinstance(obj, dict) and keys[0] in obj or \
       isinstance(obj, list) and keys[0] < len(obj):
        if len(keys) == 1:
            return obj[keys[0]]
        return dig(obj[keys[0]], *keys[1:], error=error)

    if hasattr(obj, keys[0]):
        if len(keys) == 1:
            return getattr(obj, keys[0])
        return dig(getattr(obj, keys[0]), *keys[1:], error=error)

    if error:
        raise KeyError(keys[0])

    return None

キーを用いて要素にアクセスするデータ構造(listdict や、それに類似したインタフェースを持つオブジェクト)だけでなく、普通のオブジェクトにも用いることができます。

class Hoge:
    def __init__(self, p, q, r):
        self.p = p
        self.q = q
        self.r = r


if __name__ == '__main__':
    h = { 'foo': { 'bar': { 'baz': 1 } } }
    print(dig(h, 'foo', 'bar', 'baz')) # => 1

    try:
        print(dig(h, 'foo', 'zot', 'xyz')) # => KeyError
    except KeyError as e:
        print(e) # => 'zot'

    print(dig(h, 'foo', 'zot', 'xyz', error=False)) # => None

    g = { 'foo': [10, 11, 12] }
    print(dig(g, 'foo', 1)) # => 11

    k = Hoge(1, 2, Hoge(Hoge(1, 2, 3), 4, 5))
    print(dig(k, 'r', 'p', 'p')) # => 1

    try:
        print(dig(k, 'r', 's', 'p')) # => KeyError
    except KeyError as e:
        print(e) # => 's'

このようにして用いることができます。こうして我々は掘り進めるだけでよくなります。よかったですね。

ところで、この実装にはまだ解決されていない問題があり、

hoge.method_one().method_two().destination

のようなメソッドチェーンには対応しておりません。それはまた別の話になりそうです*3

*1:個人的にこの挙動は好ましくないと考えています。なぜなら、返ってきた None が実際の要素なのか、要素が存在しなかったときの None なのか区別することができないからです。

*2:どちらも try-except でくくれば解決することではありますが……。

*3:そもそも Pythonic なのか? という議論も出てきそうなので、この辺で止めておきます。

[ディアマイレディ] 櫻井桃華

ありがとう千川ちひろ、ありがとうアイドルマスターシンデレラガールズ スターライトステージ

次回予告