python注意点まとめ

思うところあってpythonを真面目に勉強したので、ハマったことなどまとめ。

なお、特にこだわりはないけど環境はpython2

TL: DR

  • FizzBuzzブラックジャックとヒープツリーを実装してみた
  • インデントを揃える。話はそれからだ
  • phpのvar_dumpに相当する関数はない
  • unittestは標準で用意されている
  • for文を使うときはfor i in range(0, n):とする。rangeがなくても動くが、期待通りに動かない
  • implicit falseが推奨らしい

FizzBuzz

短いのでインラインで。 慣習的なものはよくわからないけど多分そんなに違わないと思う。

import sys

def fizzbuzz(n):
    ret="1"
    for i in range(2, n+1):
        if (i%15)==0:
            ret+=" FizzBuzz"
        elif (i%3)==0:
            ret+=" Fizz"
        elif (i%5)==0:
            ret+=" Buzz"
        else:
            ret+=(" "+str(i))
    print(ret)

実行結果は

$ python fizzbuzz.py 15
1 2 Fizz 4 Buzz Fizz 7 8 Fizz Buzz 11 Fizz 13 14 FizzBuzz

となる。

ブラックジャック

プログラミングのステップの1つとしてブラックジャックを実装してみるのがいいみたいなので書いてみた。

こっちもレギュレーションをきちんと確認していないので雰囲気で実装。

コードはここに

https://github.com/smitch/python-practice/blob/master/blackjack.py

結構楽しいので、時間があるときにもうちょっと詰めたい。

カードカウンティングとかも面白そう。

unittest

ブラックジャックを書いた後にunittestが標準であることに気づいた。

unittest.TestCaseを継承したクラスを作成して、メソッド名がtestで始まるメソッドを実装すればunittest.main()を呼び出すだけでテストメソッドを実行してくれる。

メソッド名がtestで始まるメソッドを実装すればよい。(大事なことなので2回言いました)

継承してメソッド実装すると、実装したメソッドを自動実行するっていうのも面白い仕様だと思った。時間があるときにunittestの実装もみてみよう。

なお、pythonの実行時に-vオプションを付けることでテストの情報が出力される。

詳しいことはここに

unittest --- ユニットテストフレームワーク — Python 3.7.4 ドキュメント

ヒープツリー実装

そこそこ真面目なヒープツリー実装のはず。。。

python標準ライブラリのheapqはリスト実装だけど、今回はグラフを使ったツリー構造での実装。

https://github.com/smitch/data_structure_and_algorithm/blob/master/tree/heap_tree.py

iteratorとyield

yieldを使うと明示的に状態を持たなくてもiteratorが実装できる。

yieldでヒープツリーのDFSを実装するとこんな感じ。

    def dfs_iter(self, current=None):
        if current is None:
            current = self.root
        yield current
        if current.left is not None:
            for i in self.dfs_iter(current.left):
                yield i
        if current.right is not None:
            for i in self.dfs_iter(current.right):
                yield i
        raise StopIteration

最初、yieldはreturn的な動作だと思ったが、returnとは切り離して考えた方が良さそう。

yieldの流れは、

  1. yieldを使うメソッドを呼び出すと、generatorが返ってくる。

  2. 得られたgeneratorのnext(next)メソッドを呼び出すことで、実際のメソッドの中身が実行される。

となる。

for文と合わせて使うと自然に使える。

ちょっと特殊な感じがするけど、慣れると便利そう。

pydoc

pydoc <module name>

にてドキュメントが生成される。

モジュール名はファイル名から.pyを除いたもの

pycheck

pipでインストールする。

pychecker <file name>

にて構文のチェックを行なえる。

細かい設定はまだ追えていない。

pylintとかも調べたい。

python style guide

pythonのスタイルは大きくgoogle styleとnumpy styleの2つがあるらしい。

今回はgoogle styleを参考にした。

https://github.com/google/styleguide/blob/gh-pages/pyguide.md

var_dump

pprint.pprint(vars(a))などでインスタンス変数の一覧を出力できる。

内部的にはvarsはa.__dict__を出力している模様。

なお、printを実行すると__str__が呼ばれる。

特殊属性、メソッドは把握しきれていないので、きちんとまとめたい。

このサイトはかなり参考になった。

特殊メソッド名 - Dive Into Python 3 日本語版

implicit falseとNone

  • 変数が0,[],False, None等の場合の分岐はif a:の表記が推奨。ただし、0Falseを区別したい場合には使えない。
  • 変数とNoneの比較はしてはいけない。if a is Noneと書く。

NoneTrueでもFalseでもない。ちょっと人工的な例だけど下のようなコードを書くとハマる。

if a == True:
    print "true"
elif a == False:
    print "false"
else:
    print "a is neigher True nor False!"

python2とpython3の違い

ここまでやってみて気づいた点

  • printがpython2では構文だがpython3では関数
  • イテレータの次の要素の取得がpython2ではnextだがpython3では__next__
  • python2ではprintで末尾に必ず改行が入る。

今後やりたいこと

  • assertに引っかかったらプログラム停止して、インタラクティブモードになるようにしたい。どこかのサイトに実装があったはず。

スピードキューブで1分以内に揃えられるようになった

「時間かければ揃えられる(2分以内くらい)」→「1分以内に揃えられる」までトレーニングしたのでメモ書き。

1分以内は手順覚えて練習すれば出来るみたいな記事があるけど、実際どれくらいのレベルなのかを書いておく。

TL; DR

  • 手が常に動く程度にキューブの状態を確認出来るようになれば60秒以内は達成できる

  • 揃え方のパターンは覚えこまなくてもいい(F2Lのパターンなど)

  • タイマーアプリを活用する

現在のレベル

基本的にはLBLやCFOPな揃え方をしているが、揃え方が我流なので一般的なのより効率悪いかも。 いろいろ考えてやっていくのが楽しいというスタイルなので、今の段階では覚えるのはあまりしない。 1分切れるようになったので、おいおい一般的なのも覚えていきたい。

具体的な手順は時間があるときにまとめたい。

やっている揃え方とおおよその所要時間

  • cross

とにかく揃える。それだけ。目標10秒以内だけど15秒くらいかかることもある。

現状のレベルだと、インスペクションの15秒ですべて読みきるのは結構きつい。 大体3つは読んで、最後は場当たりで揃えることが多い。ひどい時は2つまでしか読めないが、その際は1分はかなりきつい。

  • F2L

当初は1層目、2層目の順でやっていたけど、入れられるところからこだわらずにやったほうが速かった。

キューブを探すのに時間が掛からないようにする。

現状だと、次に揃えるキューブの場所のあたりはつくけど、向きとかが正確に把握できていないので、 一旦動きを止めて確認する必要がある。このあたりは今後の改善点

ここまでで35秒くらいかかる。

  • OLL(コーナーキューブ)

まず、last layerのコーナーキューブの位置を調整する。 PLLの前にするのは理由が2つある。

1つ目は単純に、いわゆるUパームの手順を知らないから。つまり、PLLしてからPLLされた状態に戻しつつコーナーキューブの入れ替えをする手順を知らないからやっていない。

2つ目は、こっちのほうが入れ替えの操作回数は少なくなると思っているから。キューブの状態確認に時間がかからなければ、PLLを気にしなくていい分、早めに操作したほうが手順が少ないと思う。

なお、エッジキューブの位置調整はこの段階ではしない。

だいたいここまでで43秒くらい。45秒までかかると後がきつい。

  • PLL

コーナーキューブとエッジキューブの上面の向きを揃える。

なお、コーナーとエッジキューブはそれぞれ独立した手順で揃える。

ここまでで50秒くらい。

  • OLL(エッジキューブ)

エッジキューブの並び次第で、同じ手順を0〜2回繰り返すことになる。

順調にできていないと手順2回だと1分以内はきつい。

タイマーアプリについて

スマホアプリが有能。

数は試してないけどこれが良かった。

play.google.com

機能としては

  • タイマー機能

  • スクランブル生成

  • 記録の統計

があるので、かなり練習が捗る。

スタックタイマーのデザインになっているので雰囲気もそれっぽくなる。

改善点と今後の目標

40秒切るくらいまでは現状の改善でできそうな気がする。 具体的には、 - クロスはインスペクションで読みきって、10秒で確実に揃える。可能であればF2Lも少し読む。 - F2Lでコーナーキューブとエッジキューブを同時に揃える - OLLの手順が少なくなるようF2Lの手順を調整する - OLL、PLLでキューブの状態を逐次確認しなくても良くなるよう、連続した手順を行えるようにする

F2Lの短縮が大きく効きそうなのでそこを重点的にしたい。 パターンごとの手順を覚えなくても、キューブの状態の把握の向上と、特定の手順を行った時にその他のキューブがどう動くのかを読めるようになれば自然とF2Lで出来るようになると思う。

とりあえず1分切ったので、40秒まではぼちぼちなペースでやっていくつもりである。 手順は意識せずに、継続練習でキューブの状態把握の向上を半年くらいやってみようと思う。

postfixの設定を見直した

TL; DR

  • 自前のメールサーバから送ったメールがgmailで”暗号化されませんでした”と表示されるので、tls関係の設定を変更した
  • postfixの設定のプレフィクスには”smtp_”と”smtpd_”の2種類がある
  • postfixの設定のプレフィクスには”smtp_”と”smtpd_”の2種類がある (大事な事なので…以下省略

smtpとsmtpd

メーラ→メールサーバ(postfix)→gmailの流れでメールを送信するケースを考える。

このとき、メーラ→メールサーバ間が”smtpd_”の設定、メールサーバ→gmailが”smtp_”の設定が該当する。

よって、gmail向けにTLSを使う場合は、”smtp”の設定でtlsを有効にする。

設定

メーラとgmail向け両方にtlsを有効にするよう設定をした。 証明書はLet’t encryptで取得しているのでそれを用いる。証明書更新時にはpostfixの再起動が多分必要。

なお、smtp_tls_CAfileは指定をしないとgmailの証明書がuntrustedとなる(ログに記録される)。

しかし、ログに記録されるだけで、httpsのように警告が出たりはしない。

unstrustedの場合に動作を変更する場合には、smtp_tls_security_levelでverifyを指定し、smtp_tls_verify_certで検証項目を指定する。

ただし、この動作はインターネットにメールを配送するシステムのデフォルト動作としては適切ではない。

また、この設定は、tlsで送信してもいいし、しなくてもいいという日和見tlsであるが、tlsを強制する設定も、インターネットにメールを配送するシステムのデフォルト動作としては適切ではない。

smtp_tls_security_level = may
smtp_tls_CAfile = /etc/pki/tls/cert.pem
smtpd_tls_cert_file = /etc/letsencrypt/live/<domain name>/fullchain.pem
smtpd_tls_key_file = /etc/letsencrypt/live/<domain name>/privkey.pem
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtp_tls_protocols = !SSLv2, !SSLv3
smtpd_tls_protocols = !SSLv2, !SSLv3
smtpd_tls_loglevel=1
smtp_tls_loglevel=1
smtpd_tls_received_header = yes

なお、postfix 2.3以降では“smtp_use_tls”を使わず、smtp_tls_security_levelを使うことになっている。

パラメータの詳細はman 5 postconfで見れる。

ウェブに比べてメールシステムの暗号化・証明書の扱いってゆるゆるですね。 そのうちメールにもtls必須とかの流れになるんでしょうか。

やりたいことリスト(2019年1月)

唐突に、やりたいことを整理するべきではないかと思ったのでまとめる。

テクニカルなこと

  • CCIE取得
  • CTFに参加
  • OSSなプロジェクトに参加
  • Topcoderでのランク上げ

日常なこと

各項目で今年中に1個ずつ出来ればいいなと思っている。

書いてみて改めて思ったけど、何をしたいのか自分でもよくわかんないです。

そのあたり含めてきちんと考えていくためにも、きちんと何をしたいのかと出来ているのかの記録を残すことに意味がありそうな気がしている。

時期を見てレビューする。(3月にする予定)

asciinemaでGNU screenの操作を記録する

作業ログ残すのにasciinemaが便利そうと思った際に、screenとの連携がどうなるか気になったので動作確認をした。

そのままasciinemaを実行すると、screen内でasciinemaを実行したwindowの記録しか取ってくれない。

そのため、asciinemを”-c screen“オプションをつけて、

asciinema rec <filename> -c screen

と実行する(新たにscreenが起動される)。

これにより、screen内の動作全てを記録することができる。

正常終了はもちろんデタッチした際にも記録が止まる。

また、リタッチもうまく動作し、

asciinema rec <filename> -c “screen -r [<pid>]”

のようにすることで、リタッチしての記録ができる。

実際の動作はこんな感じ。

CPU換装とベンチマーク

CPUを換装したのでベンチマークをとってみる。

ベンチマーク: UnixBench
OS: Ubuntu 14.04 LTS (GNU/Linux -- 4.4.0-134-generic)

結果は以下の通り。温度はベンチマーク終了後の各CPUの平均温度。

CPU CPUクーラー スコア(1process) スコア(マルチプロセス) 温度
Intel(R) Core(TM)2 Duo CPU E7200 リテール品 492.4 352.1 60度
Intel(R) Core(TM)2 Quad CPU Q6600 リテール品 547.8 785.4 83度
Intel(R) Core(TM)2 Quad CPU Q6600 IZUNA SCIZN-1000I 504.7 799.1 57度

やっぱりCPUやファンを変えると随分温度が違う。

レビューに書いてあったが、IZUNAは取り付けづらい。。。

プッシュピン式なのにマザーボード取り出して取り付けたが、それでもきちんとハマった気がしない感じで運用している。

sambaでクライアント側でnetwork unreachableエラーが発生した

ただの設定ミスだったが、案外確認に手間取ったのでメモ。

状況

sambaでファイル共有しようとしたところ、tcp 139への接続が3wayハンドシェイク後にicmpのnetwork unreachableで切られていた。

エラーとしては

Error code: Not listening for calling name (0x81)

となっていた。

原因

sambaで接続元のIPアドレスを制限しており、接続元のIPアドレスが含まれていなかった。

対応

sambaのIPアドレスの制限を設定変更して解消。