2020年3月21日土曜日

デバッグ注意

関数値の戻り値の型に注意!



以下をみてもらいたい
なぜか、
実際にはバグでFalseでなく0が返却されてと仮定します。

if文で比較時にキャストされてしまい、Falseになるのです。

>>> a
0
>>> bool(a)
False



a=func1()
#a=0
if a== False :print "OK" # OKが出力された


>>> assert isinstance( a, bool )
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AssertionError




改善策
func1は、数字が返却とは、想定していなかった
==>assertを使用して関数の戻り値をチェックする

a=func1()
#a=0

assert isinstance( a, bool )
if a== False :print "OK" # OKが出力された


*ちょっと一般的に設計したがる戻り値

正常の場合は、整数値を返却する
エラーの場合は、Falseを返却

例題で、こんなものはどうだろうか?
あまり処理内容は意味がないが
(ただし、戻り値0もあり)

def func2(num):

 data  = num * 2 -10
 if data <0:
  return False
else:
 return data


ret = func2( 5 )
if ret == False :
 print("error")
else:
 print("num=", ret)

改善策!
if  isinstance( ret, bool ) and ret == False :
 print("error")
else:
 print("num=", ret)

でも、もっと良い方法がある「is」を使うのである
「is」は同一オブジェクトかを判定する。

if  ret is False :
 print("error")
else:
 print("num=", ret)




個々のオブジェクト(インスタンス)には、idが振られている。
id( 調べたいオブジェクト )で調べられ、同一オブジェクト化を判定できる


結論
・if文で比較の場合、
比較がTrueかFalseしかないと断言できる場合は
if data:~
if not data:~
がわかりやすい!
しかし、assertを入れておくと保険になりますよ!

・if文で比較の場合、
比較がTrueかFalseしかないと断言が心配なら
if data is True等がベストです。

※「==」は、キャストが行われるので…




assertは,
__debug__(組み込み定数)がTrueの時実行、通常はTrue
assertさせないは、
起動時のコマンドラインのオプションで「-O」にする
(同時に__debug__がFalseになる)


結論2
Noneも同様がわかりやすいね(スピードがはやい)
 if data is None: ~

まとめ
if data is True:~
if data is False:~
if data is None:~
if data is not None:~