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