最近、面白い、トリッキー、そして奇妙なJavaScriptの例について書きました 。 今ではPythonの番です。 高度なインタープリター型言語であるPythonには、多くの便利なプロパティがあります。 しかし、一見したところ一部のコードの結果が明らかでない場合があります。
以下は、Pythonでの予期しない動作の例を収集し、内部で何が起こるかを議論する楽しいプロジェクトです。 いくつかの例は、実際のWTFのカテゴリに属していません!?、しかし、それらはあなたが避けたい言語の興味深い特徴を示しています。 これはPythonの内部の仕組みを学ぶ良い方法だと思います。興味を持っていただければ幸いです。
既に経験豊富なPythonプログラマーである場合、多くの例はあなたによく知られているかもしれませんし、それらに頭を悩ませるとき、それらの場合に懐かしささえ引き起こすかもしれません:)
内容
- 例の構造
- 使用する
- 例
- 行スキップ?
- まあ、どういうわけか怪しい...
- ハッシュケーキの時間!
- 処理時間の不一致
- 反復中に辞書を変換する
- 反復中にリストアイテムを削除する
- 行末のバックスラッシュ
- 巨大な糸を作ろう!
- 文字列連結インタープリターの最適化
- はい、存在します!
-
is
そうではis
ません -
is not ...
is (not ...)
- ループ内の関数は同じ結果を生成します。
- ローカルスコープからのループ変数の漏洩
- 三目並べ、最初の試行でXが勝つ
- 可変のデフォルト引数に注意してください
- オペランドは同じですが、ストーリーが異なります
- 不変の変更
- スコープで定義されていない変数を使用する
- 外部スコープからの変数の消失
- どこでも返品
- Trueが実際にFalseの場合
- チェーン操作には注意してください。
- 名前解決はクラススコープを無視します
- 1つの命令でフルからなしへ
- 文字列値の明示的な型変換
- クラスとインスタンスの属性
- 例外をキャッチする
- 真夜中は存在しませんか?
- ブール値の何が問題になっていますか?
- 干し草の山の針
- 何のために?
- ノードではない
- そのようなことを提案してもらえますか?
- 小さな例
- 貢献する
- 便利なリンク
例の構造
注:上記の例はすべて、対話型Python 3.5.2インタープリターでテストされており、説明で特に指定されていない限り、すべてのバージョンの言語で動作するはずです。
例の構造:
いくつかの愚かな見出し
# . # ...
結果(Pythonバージョン):
>>> _ ,
(オプション):予期しない結果の1行の説明。
説明
何が起こったのか、そしてその理由の簡単な説明。
( )
結果:
>>> # - , #
使用する
これらの例を最大限に活用する最善の方法は、時系列でそれらを読むことであるように思えます。
ソースコードを注意深く調べてください。 あなたが経験豊富なPythonプログラマである場合、ほとんどの場合、何が起こるかをうまく予測できます。
結果を調査するには:
- 彼らがあなたの期待と一致するかどうかを確認してください。
- そのような結果が得られる理由を必ず理解してください。
- わからない場合は、説明を読んでください(まだわからない場合は、 ここで叫んでください )。
- 理解したら、頭を軽くたたいて次の例に進んでください。
PSコマンドラインでこれらの例を読むこともできます。 wtfpython
にwtfpython
npmパッケージをインストールするだけで、
$ npm install -g wtfpython
コマンドラインでwtfpython
を実行すると、このコレクションが$PAGER
開きます。
#TODO:pypiパッケージを追加して、コマンドラインで読み取ります。
例
行スキップ?
結果:
>>> value = 11 >>> valu = 32 >>> value 11
ワット?
注:この例を再現する最も簡単な方法は、ファイル/シェルにコピーして貼り付けることです。
説明
一部のUnicode文字はASCIIと同じように見えますが、インタープリターによって異なります。
>>> value = 42 #ascii e >>> valu = 23 #cyrillic e, Python 2.x interpreter would raise a `SyntaxError` here >>> value 42
まあ、どういうわけか怪しい...
def square(x): """ . """ sum_so_far = 0 for counter in range(x): sum_so_far = sum_so_far + x return sum_so_far
結果(Python 2.x):
>>> square(10) 10
100ではないでしょうか?
注:結果を再現できない場合は、シェルでmixed_tabs_and_spaces.pyファイルを実行してみてください。
説明
- タブとスペースを混在させないでください! リターンの前の文字はタブであり、4つのスペースとして認識されます。
- Pythonがタブを処理する方法を次に示します。
最初に、それらは(左から右へ)1から8までのスペースで置き換えられるため、置き換えられる文字の合計数は8倍以上になる可能性があります... - したがって、
square
関数の最後の行のタブは8つのスペースに置き換えられ、ループに入ります。 - そのような場合、Python 3は自動的にエラーをスローできます。
結果(Python 3.x):
TabError: inconsistent use of tabs and spaces in indentation
ハッシュケーキの時間!
1。
some_dict = {} some_dict[5.5] = "Ruby" some_dict[5.0] = "JavaScript" some_dict[5] = "Python"
結果:
>>> some_dict[5.5] "Ruby" >>> some_dict[5.0] "Python" >>> some_dict[5] "Python"
PythonはJavaScriptの存在を破壊しましたか?
説明
Pythonの辞書は、等価性をチェックし、ハッシュの値を比較して、2つのキーが同じかどうかを判断します。
Pythonで同じ値を持つ不変オブジェクトは、常に同じハッシュを取得します。
>>> 5 == 5.0 True >>> hash(5) == hash(5.0) True
注:異なる値を持つオブジェクトも同じハッシュを受け取ることができます(この状況はハッシュ衝突と呼ばれます)。
some_dict[5] = "Python"
式を実行すると、Pythonがsome_dict
同じ辞書キーとして5
および5.0
を認識するため、既存の "JavaScript"式は "Python"に書き換えられます。
StackOverflow は、この動作の理由を完全に説明しています。
処理時間の不一致
array = [1, 8, 15] g = (x for x in array if array.count(x) > 0) array = [2, 8, 22]
結果:
>>> print(list(g)) [8]
説明
- 句ジェネレーター式
in
、in
宣言時に処理され、条件付き句は実行時に処理されます。 - したがって、実行前に
array
はリスト[2, 8, 22]
2、8、22]に再割り当てされ、1、8、および15
うちカウンター8
の値のみが0
より大きいため、ジェネレーターは8
のみを8
ます。
反復中に辞書を変換する
x = {0: None} for i in x: del x[i] x[i+1] = None print(i)
結果:
0 1 2 3 4 5 6 7
はい、 8回実行されて停止します。
説明
- この言語は、編集中の辞書を反復する機能をサポートしていません。
- この時点で辞書が拡大されてより多くのキーが保持されるため、8回実行されます(8つの削除レコードがあるため、辞書のサイズを変更する必要があります)。 これらは実装機能です。
- 同様の例がStackOverflowによって解析されます。
反復中にリストアイテムを削除する
list_1 = [1, 2, 3, 4] list_2 = [1, 2, 3, 4] list_3 = [1, 2, 3, 4] list_4 = [1, 2, 3, 4] for idx, item in enumerate(list_1): del item for idx, item in enumerate(list_2): list_2.remove(item) for idx, item in enumerate(list_3[:]): list_3.remove(item) for idx, item in enumerate(list_4): list_4.pop(idx)
結果:
>>> list_1 [1, 2, 3, 4] >>> list_2 [2, 4] >>> list_3 [] >>> list_4 [2, 4]
結果が得られた理由を知っていますか[2, 4]
?
説明
反復中にオブジェクトを変更することは常に悪い考えです。 それから
list_3[:]
がするように、オブジェクトのコピーを反復する方が良いです。
>>> some_list = [1, 2, 3, 4] >>> id(some_list) 139798789457608 >>> id(some_list[:]) # Notice that python creates new object for sliced list. 139798779601192
del
、remove
およびpop
の違い:
del var_name
は、ローカルまたはグローバル名前空間のvar_name
バインディングを単に削除します(したがって、list_1
は影響を受けません)。
remove
は、特定のインデックスではなく、最初に一致した値remove
削除し、値がない場合はValueError
を上げます。
pop
は、特定のインデックスを持つ要素を削除して返し、無効なインデックスが指定されている場合はIndexError
を上げます。
なぜそれが起こったのか[2, 4]
?
- リストはインデックス
list_4
、list_2
またはlist_4
から1
を削除すると、リストの内容は[2, 3, 4]
ます。 残りのものは下にシフトされます。つまり、2
はインデックス0に、3
はインデックス1にあります。次の反復はインデックス1(3
)に対して実行されるため、2
はスキップされます。 リスト内の2番目の要素ごとに同じことが起こります。 Pythonの辞書に関連する同様の例は 、StackOverflowで美しく説明されています。
行末のバックスラッシュ
結果:
>>> print("\\ some string \\") >>> print(r"\ some string") >>> print(r"\ some string \") File "<stdin>", line 1 print(r"\ some string \") ^ SyntaxError: EOL while scanning string literal
説明
-
r
プレフィックスで示される生の文字列リテラルでは、バックスラッシュには特別な意味はありません。 - ただし、インタープリターはバックスラッシュの動作を変更するため、バックスラッシュと後続の文字は単にスキップされます。 したがって、生の行の末尾にあるバックスラッシュは機能しません。
巨大な糸を作ろう!
これはまったくWTFではありませんが、いくつかのクールなことだけであり、注意する必要があります:)
def add_string_with_plus(iters): s = "" for i in range(iters): s += "xyz" assert len(s) == 3*iters def add_string_with_format(iters): fs = "{}"*iters s = fs.format(*(["xyz"]*iters)) assert len(s) == 3*iters def add_string_with_join(iters): l = [] for i in range(iters): l.append("xyz") s = "".join(l) assert len(s) == 3*iters def convert_list_to_string(l, iters): s = "".join(l) assert len(s) == 3*iters
結果:
>>> timeit(add_string_with_plus(10000)) 100 loops, best of 3: 9.73 ms per loop >>> timeit(add_string_with_format(10000)) 100 loops, best of 3: 5.47 ms per loop >>> timeit(add_string_with_join(10000)) 100 loops, best of 3: 10.1 ms per loop >>> l = ["xyz"]*10000 >>> timeit(convert_list_to_string(l, 10000)) 10000 loops, best of 3: 75.3 µs per loop
説明
- timeitについて詳しく読むことができます。 通常、コードフラグメントの実行時間を測定するために使用されます。
-
+
を使用して長い文字列を生成しないでくださいstr
では、str
は不変です。そのため、連結の各ペアについて、左右の文字列を新しい行にコピーする必要があります。 それぞれ10文字の4行を連結する場合、(10 + 10)+((10 + 10)+ 10)+(((10 + 10)+10)+10)= 40ではなく90文字をコピーします。行の数とサイズは4倍悪いです。 - したがって、
.format.
構文を使用する.format.
または%
(ただし、短い行ではこれは+より少し遅くなります)。 - また、コンテンツが反復可能なオブジェクトとして既に利用可能な場合は、より高速なものを選択することをお
''.join(iterable_object)
ます。''.join(iterable_object)
。
文字列連結インタープリターの最適化
>>> a = "some_string" >>> id(a) 140420665652016 >>> id("some" + "_" + "string") # Notice that both the ids are same. 140420665652016 # using "+", three strings: >>> timeit.timeit("s1 = s1 + s2 + s3", setup="s1 = ' ' * 100000; s2 = ' ' * 100000; s3 = ' ' * 100000", number=100) 0.25748300552368164 # using "+=", three strings: >>> timeit.timeit("s1 += s2 + s3", setup="s1 = ' ' * 100000; s2 = ' ' * 100000; s3 = ' ' * 100000", number=100) 0.012188911437988281
説明
-
+=
高速+
2行以上。最初の行(たとえば、s1 += s2 + s3
)は、行全体が処理されるまで破棄されないためです。 - 両方の行は同じオブジェクトを参照します。CPythonの最適化は、毎回新しいオブジェクトを作成するのではなく、既存の不変オブジェクト(実装機能)を使用しようとする場合があるためです。 続きを読む 。
はい、存在します!
forループのelse
節 。 典型的な例:
def does_exists_num(l, to_find): for num in l: if num == to_find: print("Exists!") break else: print("Does not exist")
結果:
>>> some_list = [1, 2, 3, 4, 5] >>> does_exists_num(some_list, 4)
あります!
>>> does_exists_num(some_list, -1)
存在しません。
例外処理のelse
句 。 例:
try: pass except: print("Exception occurred!!!") else: print("Try block executed successfully...")
結果:
Try block executed successfully...
説明
-
else
は、すべての反復後に明示的なbreak
がない場合にのみ、ループの後に実行されます。 -
try
ブロックのelse
節は、完了節とも呼ばれますtry
式のelse
は、try
ブロックが正常に完了したことを意味するためです。
is
そうではis
ません
この例は非常に広く知られています。
>>> a = 256 >>> b = 256 >>> a is b True >>> a = 257 >>> b = 257 >>> a is b False >>> a = 257; b = 257 >>> a is b True
説明
is
と==
の違い
-
is
演算子は、両方のオペランドが同じオブジェクトを参照していることを確認します(つまり、互いに同一であるかどうかを確認します)。 -
==
演算子は、オペランドの値を比較し、同一性をチェックします。 - したがって、リンクの等価性に使用され、
==
は値の等価性に使用されます。 説明例:
>>> [] == [] True >>> [] is [] # These are two empty lists at two different memory locations. False
256
は既存のオブジェクトですが、 257
はそうではありません
Pythonを起動すると、-5〜256の数値がメモリに割り当てられます。 これらは頻繁に使用されるため、準備を整えておくことをお勧めします。
https://docs.python.org/3/c-api/long.htmlから引用
現在の実装では、-5〜256のすべての数値に対して整数オブジェクトの配列がサポートされているため、この範囲からintを作成すると、既存のオブジェクトへのリンクが取得されます。 したがって、値を1に変更できるはずです。しかし、この場合、Pythonの動作は予測不能になると思われます。 :-)
>>> id(256) 10922528 >>> a = 256 >>> b = 256 >>> id(a) 10922528 >>> id(b) 10922528 >>> id(257) 140084850247312 >>> x = 257 >>> y = 257 >>> id(x) 140084850247440 >>> id(y) 140084850247344
インタープリターはそれほどスマートではなく、実行時にy = 257
は値257
整数を既に作成したことを理解していなかったため、メモリ内に別のオブジェクトを作成します。
a
とb
は、同じ行に同じ値を持つ初期化中に同じオブジェクトを参照します。
>>> a, b = 257, 257 >>> id(a) 140640774013296 >>> id(b) 140640774013296 >>> a = 257 >>> b = 257 >>> id(a) 140640774013392 >>> id(b) 140640774013488
-
257
同じ行のb
とb
に割り当てられると、Pythonインタープリターは新しいオブジェクトを作成すると同時に、2番目の変数からそれを参照します。 異なる行に値を割り当てた場合、インタプリタはオブジェクトの形式ですでに257
を持っていることを「認識」しません。 - これは、対話型環境に特に適用されるコンパイラ最適化です。 作業中のインタープリターに2行入力すると、それらがコンパイルされます。つまり、別々に最適化されます。
.py
ファイルでこの例を実行しようとしても、ファイルは一度にコンパイルされるため、この動作は見られません。
is not ...
is (not ...)
>>> 'something' is not None True >>> 'something' is (not None) False
説明
-
is not
は単独のバイナリ演算子でis
not
、is
とnot
が別々に使用される場合の動作とは動作が異なります。 - ステートメントの両側の変数が同じオブジェクトを指す場合、
False
返しis not
。 それ以外の場合は、True
がTrue
ます。
ループ内の関数は同じ結果を返します。
funcs = [] results = [] for x in range(7): def some_func(): return x funcs.append(some_func) results.append(some_func()) funcs_results = [func() for func in funcs]
結果:
>>> results [0, 1, 2, 3, 4, 5, 6] >>> funcs_results [6, 6, 6, 6, 6, 6, 6]
some_func
をfuncs
に追加する前に、各反復のx
値が異なる場合、すべての関数は6を返しました。
//OR >>> powers_of_x = [lambda x: x**i for i in range(10)] >>> [f(2) for f in powers_of_x] [512, 512, 512, 512, 512, 512, 512, 512, 512, 512]
説明
- 本体でループ変数が使用されるループで関数を定義する場合、ループ関数のクロージャーは値ではなく変数に関連付けられます。 したがって、すべての関数は、計算に変数に割り当てられた最後の値を使用します。
- 目的の動作を得るために、ループ変数を名前付き変数として関数に渡すことができます。 なぜ機能するのですか? このようにして、変数は再び関数のスコープ内で定義されるためです。
funcs = [] for x in range(7): def some_func(x=x): return x funcs.append(some_func)
結果:
>>> funcs_results = [func() for func in funcs] >>> funcs_results [0, 1, 2, 3, 4, 5, 6]
ローカルスコープからのループ変数の漏洩
1。
for x in range(7): if x == 6: print(x, ': for x inside loop') print(x, ': x in global')
結果:
6 : for x inside loop 6 : x in global
ただし、 x
スコープ外のループに対して定義されていません。
2。
# This time let's initialize x first x = -1 for x in range(7): if x == 6: print(x, ': for x inside loop') print(x, ': x in global')
結果:
6 : for x inside loop 6 : x in global
3。
x = 1 print([x for x in range(5)]) print(x, ': x in global')
結果(Python 2.xの場合):
[0, 1, 2, 3, 4] (4, ': x in global')
結果(Python 3.xの場合):
[0, 1, 2, 3, 4] 1 : x in global
説明
- Pythonでは、forループは、特定のループ変数を気にせずに、存在する可視性スペースを使用します。 これは、以前にグローバル名前空間でforループ変数を明示的に定義した場合にも適用されます。 次に、既存の変数に関連付けられます。
- リスト内包表記の例のPython 2.xインタープリターとPython 3.xインタープリターの結果の違いは、 Python 3.0の新機能ドキュメントに記載されている変更を使用して説明できます。
「構文形式
[... for var in item1, item2, ...]
、リストの生成ではサポートされなくなりました。 代わりに[... for var in (item1, item2, ...)]
使用してください。 また、リスト生成には異なるセマンティクスがあることに注意してください。list()
コンストラクター内の生成式に関しては構文糖に近いため、特にループ制御変数が周囲のスコープに漏れることはありません。
三目並べ、最初の試行でXが勝つ
# Let's initialize a row row = [""]*3 #row i['', '', ''] # Let's make a board board = [row]*3
結果:
>>> board [['', '', ''], ['', '', ''], ['', '', '']] >>> board[0] ['', '', ''] >>> board[0][0] '' >>> board[0][0] = "X" >>> board [['X', '', ''], ['X', '', ''], ['X', '', '']]
しかし、3つのXは割り当てませんでしたか?
説明
この視覚化は、 row
変数が初期化されたときにメモリで何が起こるかを説明しています。
board
row
を乗算して初期化されると、これはメモリ内で発生します( board[0]
、 board[1]
およびboard[2]
各要素は、 row
指定された同じリストへのリンクです)。
可変のデフォルト引数に注意してください
def some_func(default_arg=[]): default_arg.append("some_string") return default_arg
結果:
>>> some_func() ['some_string'] >>> some_func() ['some_string', 'some_string'] >>> some_func([]) ['some_string'] >>> some_func() ['some_string', 'some_string', 'some_string']
説明
- Pythonでは、可変のデフォルト引数は実際にはすべての関数呼び出しで初期化されるわけではありません。 代わりに、新しく割り当てられた値がデフォルト値として使用されます。
some_func
引数として明示的に[]
を渡した場合、default_arg
デフォルト値と一緒に使用さdefault_arg
なかったため、関数は予期したものを返しました。
def some_func(default_arg=[]): default_arg.append("some_string") return default_arg
結果:
>>> some_func.__defaults__ #This will show the default argument values for the function ([],) >>> some_func() >>> some_func.__defaults__ (['some_string'],) >>> some_func() >>> some_func.__defaults__ (['some_string', 'some_string'],) >>> some_func([]) >>> some_func.__defaults__ (['some_string', 'some_string'],)
- 可変引数によるバグを回避する標準的な方法は、デフォルト値として
None
を割り当て、この引数に対応する関数に値が渡されるかどうかを確認することです。 例:
def some_func(default_arg=None): if not default_arg: default_arg = [] default_arg.append("some_string") return default_arg
オペランドは同じですが、ストーリーが異なります
1。
a = [1, 2, 3, 4] b = a a = a + [5, 6, 7, 8]
結果:
>>> a [1, 2, 3, 4, 5, 6, 7, 8] >>> b [1, 2, 3, 4]
2。
a = [1, 2, 3, 4] b = a a += [5, 6, 7, 8]
結果:
>>> a [1, 2, 3, 4, 5, 6, 7, 8] >>> b [1, 2, 3, 4, 5, 6, 7, 8]
説明
- 式
a += b
は、a = a + b
と同じ動作をしません。 - 式
a = a + [5,6,7,8]
は、新しいオブジェクトを生成し、b
変更せずに参照を割り当てます。 - 式
a + =[5,6,7,8]
実際にextend関数にマッピングされ、a
とb
がその場で変更された同じオブジェクトを指すようにオブジェクトを操作します。
不変の変更
some_tuple = ("A", "tuple", "with", "values") another_tuple = ([1, 2], [3, 4], [5, 6])
結果:
>>> some_tuple[2] = "change this" TypeError: 'tuple' object does not support item assignment >>> another_tuple[2].append(1000) #This throws no error >>> another_tuple ([1, 2], [3, 4], [5, 6, 1000]) >>> another_tuple[2] += [99, 999] TypeError: 'tuple' object does not support item assignment >>> another_tuple ([1, 2], [3, 4], [5, 6, 1000, 99, 999])
しかし、タプルは不変ですよね...
説明
- https://docs.python.org/2/reference/datamodel.htmlから引用
不変のシーケンス型オブジェクトは、作成後に変更できません。 オブジェクトに他のオブジェクトへの参照が含まれている場合、これらのオブジェクトは変更可能であり、変更できます。 ただし、不変オブジェクトによって直接参照されるオブジェクトのコレクションは変更できません。
-
+=
演算子は、リストをその場で変更します。 アイテムの割り当ては機能しませんが、例外が発生した場合、アイテムは既にその場所で変更されています。
スコープで定義されていない変数を使用する
a = 1 def some_func(): return a def another_func(): a += 1 return a
結果:
>>> some_func() 1 >>> another_func() UnboundLocalError: local variable 'a' referenced before assignment
説明
- スコープ内の変数を割り当てると、そのスコープに対してローカルになります。 つまり、aは
another_func
のスコープのローカル変数になりますが、エラーをスローする同じ領域で以前に初期化されていませんでした。 - Pythonで名前空間とスコープ解決がどのように機能するかについて詳しくは、 この短くてすばらしいチュートリアルをお読みください。
-
another_func
global
を使用しa
、another_func
外部スコープ変数a
を変更します。
def another_func() global a a += 1 return a
結果:
>>> another_func() 2
外部スコープからの変数の消失
e = 7 try: raise Exception() except Exception as e: pass
結果(Python 2.x):
>>> print(e) # prints nothing
結果(Python 3.x):
>>> print(e) NameError: name 'e' is not defined
説明
出所
ターゲットas
例外がスローされた場合、except
節の最後でクリアされます。 あたかも
except E as N: foo
に変換されました
except E as N: try: foo finally: del N
これは、例外を別の名前に割り当てて、
except
句の後に参照できるようにする必要があることを意味します。 例外は、トレースバックが添付されているためクリアされます。その結果、スタックフレームで参照サイクルが形成され、次のガベージコレクションの繰り返しが終了するまで、このフレームのすべてのロケールが保持されます。
Python . , e -
except
. , . :
def f(x): del(x) print(x)
x = 5
y = [5, 4, 3]
**:**
f(x)
UnboundLocalError: local variable 'x' referenced before assignment
f(y)
UnboundLocalError: local variable 'x' referenced before assignment
x
5
y
[5, 4, 3]
- Python 2.x e `Exception()`, .
(Python 2.x):
>>> e Exception() >>> print e # Nothing is printed!
Return
def some_func(): try: return 'from_try' finally: return 'from_finally'
結果:
>>> some_func() 'from_finally'
-
try
try…finally
return
,break
continue
,finally
. -
return
.finally
,return
,finally
, .
True False
True = False if True == False: print("I've lost faith in truth!")
結果:
I've lost faith in truth!
- Python
bool
( 0 false 1 true).True
,False
bool
, -True
False
— . - Python 3 , , Python 3.x!
>>> True is False == False False >>> False is False is False True >>> 1 > 0 < 1 True >>> (1 > 0) < 1 False >>> 1 > (0 < 1) False
https://docs.python.org/2/reference/expressions.html#not-in
, a, b, c, ..., y, z — , op1, op2, ..., opN — , a op1 b op2 c… y opN z op1 b b op2 c … y opN z, , .
,
a == b == c 0 <= x <= 100
.
-
False is False is False
(False is False) and (False is False)
-
True is False == False
True is False and False == False
, (True is False
)False
,False
. -
1 > 0 < 1
1 > 0
and0 < 1
,True
. -
(1 > 0) < 1
True < 1
>>> int(True) 1 >>> True + 1 #not relevant for this example, but just for fun 2
1 < 1
False
1。
x = 5 class SomeClass: x = 17 y = (x for i in range(10))
結果:
>>> list(SomeClass.y)[0] 5
2。
x = 5 class SomeClass: x = 17 y = [x for i in range(10)]
(Python 2.x):
>>> SomeClass.y[0] 17
(Python 3.x):
>>> SomeClass.y[0] 5
- , , , .
- .
- Python 3.X (list comprehensions) .
None
some_list = [1, 2, 3] some_dict = { "key_1": 1, "key_2": 2, "key_3": 3 } some_list = some_list.append(4) some_dict = some_dict.update({"key_4": 4})
結果:
>>> print(some_list) None >>> print(some_dict) None
, / (sequence/mapping objects)
list.append
,dict.update
,list.sort
. .,None
. — , ( )
WTF, , Python . .
a = float('inf') b = float('nan') c = float('-iNf') #These strings are case-insensitive d = float('nan')
結果:
>>> a inf >>> b nan >>> c -inf >>> float('some_other_string') ValueError: could not convert string to float: some_other_string >>> a == -c #inf==inf True >>> None == None # None==None True >>> b == d #but nan!=nan False >>> 50/a 0.0 >>> a/a nan >>> 23 + b nan
'inf'
'nan'
— ( ).float
, , , «» « ».
1。
class A: x = 1 class B(A): pass class C(A): pass
結果:
>>> Ax, Bx, Cx (1, 1, 1) >>> Bx = 2 >>> Ax, Bx, Cx (1, 2, 1) >>> Ax = 3 >>> Ax, Bx, Cx (3, 2, 3) >>> a = A() >>> ax, Ax (3, 3) >>> ax += 1 >>> ax, Ax (4, 3)
2。
class SomeClass: some_var = 15 some_list = [5] another_list = [5] def __init__(self, x): self.some_var = x + 1 self.some_list = self.some_list + [x] self.another_list += [x]
結果:
>>> some_obj = SomeClass(420) >>> some_obj.some_list [5, 420] >>> some_obj.another_list [5, 420] >>> another_obj = SomeClass(111) >>> another_obj.some_list [5, 111] >>> another_obj.another_list [5, 420, 111] >>> another_obj.another_list is SomeClass.another_list True >>> another_obj.another_list is some_obj.another_list True
- . , .
-
+=
. .
some_list = [1, 2, 3] try: # This should raise an ``IndexError`` print(some_list[4]) except IndexError, ValueError: print("Caught!") try: # This should raise a ``ValueError`` some_list.remove(4) except IndexError, ValueError: print("Caught again!")
(Python 2.x):
Caught! ValueError: list.remove(x): x not in list
(Python 3.x):
File "<input>", line 3 except IndexError, ValueError: ^ SyntaxError: invalid syntax
-
except
. — , . 例:
some_list = [1, 2, 3] try: # This should raise a ``ValueError`` some_list.remove(4) except (IndexError, ValueError), e: print("Caught again!") print(e)
(Python 2.x):
Caught again! list.remove(x): x not in list
(Python 3.x):
File "<input>", line 4 except (IndexError, ValueError), e: ^ IndentationError: unindent does not match any outer indentation level
- , Python 3;
as
. 例:
some_list = [1, 2, 3] try: some_list.remove(4) except (IndexError, ValueError) as e: print("Caught again!") print(e)
結果:
Caught again! list.remove(x): x not in list
?
from datetime import datetime midnight = datetime(2018, 1, 1, 0, 0) midnight_time = midnight.time() noon = datetime(2018, 1, 1, 12, 0) noon_time = noon.time() if midnight_time: print("Time at midnight is", midnight_time) if noon_time: print("Time at noon is", noon_time)
結果:
('Time at noon is', datetime.time(12, 0)) The midnight time is not printed.
Python 3.5
datetime.time
False
, UTC. -if obj
: ,obj
null «».
?
1。
# A simple example to count the number of boolean and # integers in an iterable of mixed data types. mixed_list = [False, 1.0, "some_string", 3, True, [], False] integers_found_so_far = 0 booleans_found_so_far = 0 for item in mixed_list: if isinstance(item, int): integers_found_so_far += 1 elif isinstance(item, bool): booleans_found_so_far += 1
結果:
>>> booleans_found_so_far 0 >>> integers_found_so_far 4
2。
another_dict = {} another_dict[True] = "JavaScript" another_dict[1] = "Ruby" another_dict[1.0] = "Python"
結果:
>>> another_dict[True] "Python"
- —
int
>>> isinstance(True, int) True >>> isinstance(False, int) True
-
True
1
,False
—0
.
>>> True == 1 == 1.0 and False == 0 == 0.0 True
- StackOverflow.
Python- .
t = ('one', 'two') for i in t: print(i) t = ('one') for i in t: print(i) t = () print(t)
結果:
one two o n e tuple()
-
t = ('one',)
t = 'one'
, ( ), ,t
str
. - () — ,
tuple
.
For ?
some_string = "wtf" some_dict = {} for i, some_dict[i] in enumerate(some_string): pass
結果:
>>> some_dict # An indexed dict is created. {0: 'w', 1: 't', 2: 'f'}
-
for
Python :
for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite]
exprlist
— . ,{exprlist} = {next_value}
. @tukkek:
for i in range(4): print(i) i = 10
結果:
0 1 2 3
, ?
-
i = 10
- Python. , (range(4)
), (i
). -
enumerate(some_string)
i
(A
)some_string
. ( )i
some_dict
. :
>>> i, some_dict[i] = (0, 'w') >>> i, some_dict[i] = (1, 't') >>> i, some_dict[i] = (2, 'f') >>> some_dict
not
x = True y = False
結果:
>>> not x == y True >>> x == not y File "<input>", line 1 x == not y ^ SyntaxError: invalid syntax
- , Python
==
,not
. -
not x == y
not (x == y)
,not (True == False)
,True
. -
x == not y
SyntaxError
,(x == not) y
,x == (not y)
, . - ,
not
—not in
(==
not in
),not
in
, SyntaxError.
?
PiaFraus .
a, b = a[b] = {}, 5
結果:
>>> a {5: ({...}, 5)}
(target_list "=")+ (expression_list | yield_expression)
同様に:
( , , ) , .
-
+
(target_list "=")+
, .a
,b
a[b]
( , ,{}
,5
). - .
{}
,5
a
,b
,a = {}
b = 5
. -
a
{}
, . - —
a[b]
( , ,a
b
. ,a
{}
b
5
). -
5
({}, 5)
, ({...}
,a
). :
>>> some_list = some_list[0] = [0] >>> some_list [[...]] >>> some_list[0] [[...]] >>> some_list is some_list[0] [[...]]
(
a[b][0]
,a
)
- :
a, b = {}, 5 a[b] = a, b
,
a[b][0]
,
a >>> a[b][0] is a True
-
Join()
— (string operation), (list operation). .
:join()
— , (, , ). , . , APIlist
. - , :
-
[] = ()
(tuple
list
) -
'a'[0][0][0][0][0]
, Python . -
3 --0-- 5 == 8 --5 == 5
True
.
-
- Python . , 65 536 . Python , 2^16 . , , 65 536 (: 2^18 !):
import dis exec(""" def f():* """ + """ """.join(["X"+str(x)+"=" + str(x) for x in range(65539)])) f() print(dis.dis(f))
>>> some_list = [1, 2, 3, 4, 5] >>> some_list[111:] []
! :) CONTRIBUTING.md .
便利なリンク
• https://www.youtube.com/watch?v=sH4XF6pKKmk
• https://www.reddit.com/r/Python/comments/3cu6ej/what_are_some_wtf_things_about_python
• https://sopython.com/wiki/Common_Gotchas_In_Python
• https://stackoverflow.com/questions/530530/python-2-x-gotchas-and-landmines
• https://stackoverflow.com/questions/1011431/common-pitfalls-in-python ( StackOverflow , Python.)
- 式