夏の怪異―Python3のクラス変数のスコープ

さて、今日Pythonを書いていたら、妙なエラーに遭遇した。同じ役割を持つ変数をまとめておくためにクラス定義を用いて以下のようなコードを書いた(このようなクラスの使い方は悪くはない)。

これを見ただけで「あっ…」となる人はすごい。なんとこのコードは以下のようなエラーを吐く。

原因究明に時間を要したが、説明しているブログがあった。

【python】クラス変数のスコープには注意が必要

python - Accessing class variables from a list comprehension in the class definition - Stack Overflow

要約すると、クラス変数の中にスコープがネストされた場合、クラス変数の定義されたスコープは読まないよ、ということを言っています。リスト内包表記はスコープを作るので、この問題が起こります。

PEP 227 -- Statically Nested Scopes | Python.org

「それができるとメソッド定義で事故るだろーが、親切なpython様が対策してやってるんだよ」と書いてあります。

なるほど…。全然知らなかった。Pythonでは内側のスコープから外側のスコープを読めないということは原則的にはないので驚いた。

なお、本日書いたなかでぶっちぎりのクソコードはこれ。PythonとRubyはよくライバルみたいな扱いされるけど、こういうのを書いているとRuby使いたいと思う。でもPythonの方がライブラリが充実してるんだよなあ。

緊張感

今日は久々に他人に対して責任のあるプログラムを書いた。やはりPythonは僕のホームだ。昔から使い続けている言語なので、自分の進歩も感じられて楽しい。

明日は早い予定なので、おやすみ。

大事なことは全部

実験に必要なのでArduino(正確にはマルツ製の互換品、その名も『Marduino』)に圧力センサを繋いでPythonで読めるようにした。デバイスレベルからなんやかんやするのはかなり久しぶりだ。小学生の頃にサッカーロボットを作ったが、説明書のとおりに組み立てただけでメインはプログラミングだった。タイルを並べて条件分岐やパラメータ調節ができるようになっていたと記憶している。当時は『子供の科学』を購読していて、そこに連載されていたJavaScriptのコードを書き写して九九表を表示させたり、ちょっとした電子工作でフォトトランジスタの信号を音に変換してスピーカーをブーブー鳴らしたりして遊んでいたものだ。

それにしても当時ははんだごてを使っていて熱に弱い部品を壊してしまったこともあったが、今の電子工作はブレッドボードにピンをスポスポ刺していくだけで完成してすごい。いや、昔からブレッドボードってあったと思うんだけど、なぜだかそういうものを使った記憶がほとんどない。

圧力センサーを1つ接続したときは問題なく動作したが、2つめを並列で接続すると2つめは反応しなかった。回路の設計が悪いのか、はたまたいじっているうちにどこかを壊してしまったのかと1時間ほど悩んでいたのだが、丁寧に原因を切り分けてみるとどうやら導線のうち1本が初期不良で電流が不安定になっていたようだ。秋月で買ってきた新品なので油断していた。それにしても導線の初期不良って普通ある?どうやったら不良品作れるのよアレ。

今回の工作は実際のところネットの先人の体験談のとおりにやっただけだ。サークルの先輩の「大事なことは全部ネットに書いてある」という言葉は本当に至言だと思う。もちろんこの手の主張には「ネットに書いていないこともある」という留保がつくのがお約束だが、検索して書いてあるとおりにやるスキルさえあれば素人でもかなりいろいろなことができる時代になっていると思う。

既存のデバイスを使わずに自分で作ったのは、既存のデバイスがアメリカのいち企業によって開発されたもので、ググッてわかることが少なく、その企業の提供する様々なツールを使わないと触れなかったからだ。僕が作りたいのはあくまで実験のための道具であって芸術品ではない。素早く思い通りに操れることが大事であって、何年も使い続けられる堅牢さや充実したサポートは求めていない(そもそもいち企業が真に「充実」したサポートなど提供できるものか)。

僕がそれなりにプログラミングができるようになったのは(?)ネットの力だ。プログラミングの情報はググれば出てくる。それは凄いことだ。心理学の情報は大学がクソ高い金払って購読している論文誌を読まないとわからないからね。ググればわかることをちゃんとググれること、あるいはググればわかるようにちゃんと情報を出していくことが大事な時代だと思う。

be caught in the rain

毎週土曜はコインランドリー、そして日記もいつもコインランドリーのことを書いていてマンネリを感じないでもない。

今日はコインランドリーから帰るときに雨に降られた。といってもコインランドリーは自宅から290m徒歩3分なのでどうということはない。洗濯物も軽く乾燥して自宅で干すので多少濡れても問題ない。

雨に降られて道を走っていると、自分がその場所にいるということを強く感じる。考え事をしながらだとかツイッターを見ながら道を歩いていてもそういうことは感じないのだが、雨に降られていると早く家に帰りたいとか木の下を走ろうとか考えるので、場所や空間のことを強く意識するのだと思う。

僕はときおり、道に寝転がりたいと思う。夏の夜にコンクリートはひんやりして気持ちよさそうだと思ったり、コンクリートはどういう触感なのか気になったり、はたまた単に疲れていたり、いろいろな理由がある。しかし実際にやったことはない。小学生のころは平気で道に座って寝転がったりしただろうが、大学生になってからはない。なんどか本気で試みたのだが、ついにできなかった。誰かが見ているかもしれないとか、道は公共の場所なのでそんなことをすべきでないとか、いろいろと理由をつけてはいるが、事実として僕は道に寝転がることができない。

子供の頃は自分はなんでもわかっているつもりだったし、自分を子供扱いする大人に苛立ったりもした。そして大人になればもっと自由になれると思っていた。しかし法律的・身体的には間違いなく大人になった今、僕は「子供はものをわかっていない」と思っているし、道に寝転がる自由を失った。

ところでHyperappで2つのactionを連鎖的に呼び出したいとき、具体的にはinputへの入力をstate.onePropertyに反映しつつ、さらにその新しいstate.onePropertyに基づいてstate.anotherPropertyを再計算したいとき、どういう風に書くのが美しいのだろうか。

現状こんな風に書いているが、ひとつの関数で2つの作業をしており、美しくない。2つめ(4行目)の操作を他の場所でも使いたいときに、2つの作業を別々の関数にしておいたほうが便利だ。そう素朴に考えたのだが、

これは上手くいかない。値を入力しても即座に元の値に戻ってしまう。多分Hyperappから呼ばれるupdateにはstateが渡されるが、updateから呼ばれるupdateInputやreCalculateにはstateが渡されていない。

こうすると望み通りの動作をするが、actionsの中に形式の違う関数が混ざっていていいのかどうか疑問がある。別の場所にhelperみたいなオブジェクトを作ってそこにしまっておきたい気がする。

Hyperappは書きやすい。楽だ。しかし「どう書くべきか」というノウハウが見つからない。自由は苦痛だ。自由を捨てよ。

二日酔い回避

昨夜は相当飲んで帰宅したのだが、大量に水を飲んで寝たら二日酔いにならずに済んだ。化学には詳しくないが肝臓でアルコールを分解する化学反応のために水が必要らしい。「うおォン 俺はまるで人間火力発電所だ」ではないが、人間の体はまさに化学プラントである。

午後からゆっくり活動開始して、洗濯→松屋の回鍋肉定食→乾燥→サザエ視聴。行きつけのコインランドリーにはジャンプが置いてあったりなかったりするのだが、今日は偶然新しいジャンプが置いてあって運が良かった。ソーマがそろそろ終わりそうで驚いた。

以前からすこしずつ作っていた視覚実験用のツールがとりあえず完成した。視覚実験では呈示する刺激図形の大きさは現実空間におけるサイズではなく網膜に占めるサイズ(視角)で決める。つまりディスプレイが遠ければ刺激図形は大きくしなければならないし、逆もしかり。このツールではディスプレイサイズ、解像度、そして刺激図形の視角を入力することで、実験プログラムを組むときに刺激のサイズを何ピクセルで指定すればいいか計算してくれる。ロジックは単純で割合とtanの計算をしているだけである。

Hyperappはとても便利だった。ユーザーが入力するフォームと、その計算結果が表示されるフォームの色分けをどうしようか考えている。パッと見ただけでわかるようなデザインにしたい。

0.75春+0.25夏

※この記事はチューハイ気分(レモン)を飲みながら書かれた

僕の住居は家賃が(場所に比して)安い代わりに人権が少し減っている。隣人の炊飯器のアラームが聞こえるし、地震でもないのに揺れる。そして洗濯機置き場がない。だから僕は洗濯物をバッグに詰めて近所のコインランドリーに通う。コインランドリーに洗濯物を放り込み、近所の飲食店で適当に食事をして、コインランドリーに戻って8分間乾燥、自宅に戻って干すというのが土曜か日曜のルーチンとなっている。飲食店はこれまでは家系ラーメンが多かったが、豆板醤じゃなくて辛醤が置いてあることやラー油が置いてないことが気に入らないので最近は足が遠のきつつある。

飲食店に行って戻る間僕は近所を散歩することになるのだが、週に一度という頻度は絶妙で、季節が少しずつ変化していくのが認識できる。今日の季節はタイトルの通り0.75春+0.25夏だ。基本的には爽やかな風が半袖に気持ちいいのだが少し日差しを長く浴びていると暑いという感覚も生まれてくる。

次の休日にはおそらく暑いと感じる頻度がもっと増えているだろう。「夏だなあ」なんてことを考えているうちに夏も終わり、秋も冬も終わり、僕の人生も終わるだろう。

JavaScriptに慣れるため、Hyperappでちょっとしたカスタム検索を手作りしている。なんにしても自分の手でゼロから作ってみるというのが大事だ。Reactもいいのだろうがちょっと環境が複雑過ぎる。Hyperappも完全に理解しているわけではないが、ブラックボックスがまだ小さくて済む感覚だ。

Reactではテキストボックスへの入力はいちいちonchangeで拾ってstateに反映してやらねばならないと聞くが、これは原理主義的ではあっても効率は劣るのではないだろうか。僕のアプリに必要なのは検索ボタンが押されたときに入力されている内容であって、1文字入力されるごとに何かしたいというわけではない。Hyperappではその辺適当にやれる余地があるようだが、どのように実装するのが美しいのかよくわからない。ブラックボックスを小さめにしたいという学習上の理由からjQueryは使いたくないのだが、すくなくともgetElementById("input1").valueではないと思う。誰か教えて。

wikipediaの検索のためにMediaWiki APIを使いたいんだが、Access-Control-Allow-Originの制約によってAPIを呼び出せない。遊びで書いたPythonからは呼び出せたのに、ブラウザから呼び出すとなると禁止とは、なんともケチな話だ。

じゃあウマ娘見るね。

ScalaでOpenCVを使うときの予約語トラップ

ハマったので記録。

問題

OpenCVにはScalarというクラスがある。このクラスはvalという名のフィールドを持つがゲッターはない。値を得るためには直接アクセスする必要がある。valの型はArray[Double]であり、その先頭の値を得るために以下のようなコードを書いた。

するとエラーが出た。

解決

これはvalがScalaの予約語だからである(もちろんJavaでは違う)。

When one needs to access Java identifiers that are reserved words in Scala, use backquote-enclosed strings. For instance, the statement Thread.yield() is illegal, since yield is a reserved word in Scala. However, here's a work-around: Thread.`yield`()

(筆者訳)
Scalaでは予約語となっているようなJavaの識別子にアクセスする必要があるときは、バッククォートで囲まれた文字列を使う。たとえばThread.yield()という文はScalaではyieldが予約語なので許されない。回避策はこうだ: Thread.`yield`()

ScalaはJavaのライブラリを流用できるのでこういう事故はよくあるのだろう。

トラップ

単に予約語を識別子として用いた場合シンタックスハイライトで色がつくので気づくはずだが、今回は先頭の値にアクセスするために(0)をつけており、シンタックスハイライトが効かず発覚が遅れた。

🙂

 

Cooler Master Elite361というPCケースについて

http://apac.coolermaster.com/jp/case/mini-tower-elite-series/elite-361/
これ

ATXマザー対応でありながらコンパクトであり横置きも可能。設置スペースに制約がある場合は唯一無二のケースとなりうる。私も部屋が狭いので重宝している。一方で小さくて薄いのでパーツの制約がきつい。

幅が狭いのでCPUクーラーの高さは122mmまでと制限されているが、同様の理由でグラボを挿すと場合によっては側面ファンが設置できない。グラボの追加電源のケーブルも折り曲げることになる。具体的にはZOTAC GTX1050 LPなら側面ファンは設置できたが、ZOTAC GTX1060 AMP! Editionではダメだった。Elite361の公式ページにはグラボの長さの上限は記されているが、幅(高さ?とにかくマザーボードに対して垂直方向の寸法)の上限は記されていない。

ZOTAC GTX1050 LPの幅は70mmだが、ZOTAC GTX1060 AMP! Editionの幅は128mmである。この差で側面ファンが設置できなくなる。

Elite361に標準搭載されているファンは上部排気ファンのみである。最も近い後部のファン用の穴からの吸気が大部分を占めるだろう。となるとCPUには冷たい空気を供給できる一方で、グラボの周りには空気の流れが生じない。前述の通り側面ファン穴はグラボの真上にあるので、ここから自然吸気が行えるように、排気ファンを増設するのが妥当だろうか。あるいはグラボに冷たい空気を回すのは諦めて外排気型のグラボを買うべきだろうか。まあ問題が起きたら考える。

自作初心者は小さいケースを買うべきではない。パーツの性能上の相性以上に物理的な制約は見落としがちだからだ。

ホームページを復活させた

このホームページはしばしば消える。その理由はMySQLがしばしば原因不明のエラー(socketがない)を吐き、僕の技術では結局DBをリセットするしかなくなるからだ。

いい加減キレたので今回はdocker-composeでwordpressを立てた。

https://github.com/chao7150/myhomepage

https化も難題だった。立てたworepressのコンテナにexec -it <container id> bashで入り、certbotのインストールからapacheの設定ファイル更新まで地道にやった。

パソコン作った

  • CPU : i5-8400
  • グラフィックボード : GTX1050GTX1060(6GB)
  • メモリ : 16GB
  • SSD : 500GB
  • HDD : 1TB
  • ディスプレイ : ASUS VX24AH (24インチWQHD)
  • OS : ubuntu16.04
スペックよりもディスプレイの方が大事だと思って良いやつを買った。ドット抜けは許せないのでツクモで保証をつけた。1回交換してもらったら抜けがない個体を引けた。24インチWQHDの作業領域の広さもさることながら、この商品は発色が良い。暗い色がかなりよく区別できる。
キーボードも良いやつを買ったがまだ届いてない。液タブとのスペース問題は保留。
windowsからubuntuに変えた。ブラウザで何でも出来る時代なので特に支障なし。
CPUはi7にしても良かったのだが、昨今の脆弱性騒動やパッチによる性能低下の話を聞いて、ハイエンドにこだわるのがバカバカしくなったのでこうなった。
ゲームはDota2とかする。最高画質FHDで120Hz余裕。グラボ以上にCPUの性能が大事らしい。実際はディスプレイが60Hzなのでゲーム側で最高FPSを制限して使っている。人間の目の性能は高くないので高FPSディスプレイには価値を感じない。
opentoonzでアニメを描いたりもする。以前のPCよりも描画のカクつきが減った。詳しくないが多分グラボがopenGLをいい感じに処理してくれてるんだろう。使っている液タブ(UGEE HK1560)が安物なので若干の遅延はある。慣れればどうということはない。
液タブがubuntuで動くかどうかは心配していたが、全く問題なかった。つなぐだけで筆圧もちゃんと取れていた。
https://digimend.github.io/support/howto/drivers/evdev/
これに従ってマッピングの設定をしただけで使えた。
最近はvimの練習をしている。タイピング中に方向キーに手を伸ばすのが嫌だからだ。
 2018/2/8追記
YOLOで物体検出したくなってcuDNNで動かそうとしたらグラボのメモリが全然足りなくて詰んだので、ツクモの交換保証を発動して1060の6GBモデルを召喚した。予算オーバー。