プログラマ古いドライバが間違ったPythonのトラップと欠陥リストを持っています

コードエラーの一部は、例外がスローされた場合は、直接、私はこれは例えばトラップ、Pythonプログラマではないと思いますコードのルックスはなく、「仮定」しないように、働くことができる、「方法:トラップの私の個人的な定義はこれです。あなたは「UnboundLocalError」、例に遭遇しておく必要があります。

A = 1
デフFUNC():
... + = 1
...印刷
...
(FUNC)を
トレースバック(最新の呼び出しの最後):
ファイル"<STDIN>"、行1、<モジュール>内
のファイル「< FUNCの中STDIN>」、2行目、
UnboundLocalError:ローカル変数『』代入する前に参照さ

「UnboundLocalError」だけでなく、より高度なバージョンの場合:

輸入ランダム

デフFUNC(OK):
もしOK:
A =はrandom.Random()
他:
輸入ランダム
A = random.randint(1、10)が
返します

FUNC(真)#のUnboundLocalError:ローカル変数「ランダム」の割り当ての前に参照さ

多くのPythonの初心者のための可能な、このエラーが混乱します。しかし、私は、このコードではなく、静かに間違った方法で実行するので、与えられたことになるので、これは、罠ではないと思います。真の悪役は偽善者を恐れ、恐れていないです。私は偽善者のような欠陥だと思います。

だから、Pythonで何が本当に罠であると主張しますか?

最初:デフォルト値として可変オブジェクトへ

この推定値は、最も広くPythonや他の多くの言語、で知られているデフォルトパラメータを提供し、デフォルトのパラメータもラムダ式のため、関数呼び出し側は(そのようなGUIプログラミング、Tkinterの、QTなど)の詳細の一部を無視することができ、本当に良いことです非常に便利。しかし、あなたはデフォルト値として可変オブジェクトを使用するので、事はそれほど快適ではない場合。

DEF F(LST = []):
... lst.append(1)
... LSTを返す
...
F()
[1]
F()
[1,1]

ない驚きの驚き?その理由は、Pythonのすべてが機能も例外ではありません、デフォルトのパラメータは、プロパティの唯一の機能である、オブジェクトです。関数が評価で定義されているデフォルトパラメータ。

  関数定義が実行されたときにデフォルトのパラメータ値が評価されています。

デフォルトのパラメータではなく、時間を呼び出すのでは、定義された時に評価されている説明するために、より適切なアッパーstackoverflowの例があります。 

インポート時
デフレポート(= time.time()):
...復帰
...
レポート()
1500113234.487932
レポート()
1500113234.487932

Pythonのdocomentは、標準溶液を与えます:

  これを回避する方法は、関数の本体でそれをデフォルトとしてNoneを使用していない、と明示的にテストすることです

デフ報告(=なし):
...あるとき場合なし:
... = time.time()
...戻る
...
レポート()
1500113446.746997
レポート()
1500113448.552873

第二:X + Y = X = X + Y VS

( - OKに見えますが、必ずしも正しくないトラップの定義である)一般的に言って、二つは等価であり、少なくとも同等であるように思われます。

X = 1であり、x + = 1;印刷、X
2
、X = 1; X = X + 1、プリントX
2
、X = [1]、X + = [2];印刷X
[1]、[2]
X = [1]。 X = X + [2];印刷X
[1]、[2]

ええと、彼は光の速度の顔をヒットでしたか?

X = [1]、プリントID(x)は、X = X + [2]、プリントID(X)
4357132800
4357132728
X = [1]、プリントID(x)は、X + = [2]、プリントID(X)
4357132800
4357132800

xは効果が正しいアプリケーションシナリオに依存していることが、当然のことながら、元のオブジェクトを変更することである新しいオブジェクトX、前者ポイント。少なくとも、あなたは時々2が同じではない、知っている必要があります

括弧の第三に、マジック - ()

プログラミング言語の多様で括弧(Parentheseの)は、括弧内のPythonはまた、このタイプのデータのタプル(組)を表し、アプリケーションの広い範囲を持って、タプルは不変配列です。

=(1、2)
(A)タイプ
<タイプ'タプル'>
(())
<タイプ'タプル'>

しかし、それだけで一つの要素である場合

=(1)
(A)タイプ
<タイプ'INT'を>

マジックだけで1つの要素のタプルがある場合は、魔法ではありません、正しい姿勢は次のとおりです。

A =(1)
(A)タイプ
<タイプ'タプル'>

第四:要素のリストを生成するのリストです

これは、二次元アレイのようなビットは、もちろん、辞書要素のリストも可能である生成することで、配列の要素を生成するより一般的には、可変オブジェクトであります

非常に単純なこと:

= []×10 []、[]、[]、[]、[]、[]、[]、[]、[]、[] [0] .append(10)A [0] [10]




それは、良い無地でシンプルに見えますが、

[1]
[10] [10]、[10]、[10]、[10]、[10]、[10]、[10]、[10]、[10]、[10]

私はそれはあなたがそれを期待される結果、その理由であってはならないと思い、またはリスト内のpythonは、文言の誰もが指す上記の変数オブジェクトと変数オブジェクトであるため、正しい姿勢

A = [] _はxrange(10)のために]
[0] .append(10)[10]、[]、[]、[]、[]、[]、[]、[]、[ ]、[]]

第五に、ときに、アクセスリスト、変更のリスト

一覧(リスト)が広くpythonで使用されているリストにアクセスするとき、当然のことながら、多くの場合、いくつかの要素を追加または削除します。たとえば、次の関数は、リスト3の複数の要素を削除しようとしています。

DEF modify_lst(LST):
列挙内... IDXため、ELEM(LST):
... ELEM%3 == 0の場合:
[IDX] ...デルLST

テスト、

LST = [1,2,3,4,5,6]
modify_lst(LST)
LST
[1、2、4、5]

何も間違っていませんでしたが、それは単なる幸運だかのように

LST = [1,2,3,6,5,4]
modify_lst(LST)
LST
[1、2、6、5、4]

上記の例では、エレメント6が削除されません。modify_lst関数印刷IDX場合、アイテムは、手がかりを見つけることができる:短いにおいてLSTが、IDXがインクリメントされるので、上記の例のエラーは、それが3を除去した後、図6(LSTの最初の2つの要素になりました)0から始まります。C ++で、反復子を持つ要素を除去するために容器を通過する時間が同じ問題を抱えているかどう。

ロジックが単純な場合、リストの内包表記を使用することは良いアイデアです

第六に、閉鎖やラムダ

また、これは他の言語での長い話が似たような状況を持っている古い生徒の一例です。例を見てください:

DEF create_multipliers():
...戻り:λX iは(5)の範囲内のiについてXを*]
...
)(create_multipliersに乗算するため:
...プリント乗算器(2)
...

私は機能の複数を乗じた入力パラメータx - リストの各要素の戻り値はの関数である場合は、リストをcreate_multipliers。0,2,4,6,8の結果は。しかし、結果は5〜8、ない不慮の事故であることが期待されます。

このトラップの出現は、彼は多くの場合、ラムダを使用しているので、それが問題のラムダと考えられるが、ラムダは鍋をバックアップする抵抗を発現させることができます。問題の性質やPythonの属性のルールを検索し、LEGB(ローカル、enclousing、グローバル、bulitin)は、上記の例では、私は、クロージャはスコープ(enclousing)になっていて、Pythonの閉鎖は遅延バインディングですこれは内部関数で変数を使用クロージャの値は、クエリから呼び出されることを意味します。

解決策はつまり、ローカルスコープの閉鎖にスコープを変更する、非常に簡単です。

DEF create_multipliers():
...戻り、λX、私は= I:(5)の範囲でiについてXを*]
...

第七の定義デル

、C ++は、建設、ほとんどのコンピュータ科学専攻の学生は、最初のCデストラクタを学ぶ可能性があるという概念は非常に精通している必要があります。このように、対応する機能がある場合はPythonへの切り替えは、当然だろう。例えば、非常に有名なRAII C ++で、すなわち、定期的な声明のデストラクタを構築することにより(例えば、メモリ、ファイルディスクリプタなど)のリソースを管理することができます。それそれを行うにはどのように同じ効果を達成するために、Pythonで、破壊が呼び出されるオブジェクト関数を見つける必要が、そう見つけINITをデルの機能は、単に2つの例を書くことが実際に動作見つけることができます。しかし、実際に記述されているdocumnet pythonで、罠に陥ることがあります。

  ごみをしている循環参照はオプションサイクル検出器が有効になっている場合(それがデフォルトでオンです)検出されましたが、何のPythonレベルが存在しない場合にのみクリーンアップすることができデル()メソッドが含まれていました。

循環参照のオブジェクトが定義されている場合、単純な用語で、デル次にPythonのGCは、回復できないので、メモリリークの危険性があります

第八の、異なる姿勢は同じモジュールをインポート

例例の軽微な変更をStackOverflowの、私たちは三つのファイルパイソンが含まれていmypackageと呼ばれるパッケージ、持っているとしますmymodule.py、main.py、初期化の.pyを。次のようにmymodule.pyコードは次のとおりです。

L = []
クラスA(オブジェクト):
合格

次のようにmain.pyコードは次のとおりです。

デフ(x)を追加します。
mypackageと輸入のmymoduleから
mymodule.l.append(x)の
印刷"を更新リスト"、mymodule.l、ID(のmymodule)

デフ()を取得:
インポートのmymodule
"GETでモジュールの印刷を、ID(のmymodule)
リターンmymodule.l

場合名前 == ' メイン ':
インポートのsys
sys.path.appendが(' ../')
を追加(1)

ret = get()
print "lets check", ret

次のようにPythonのmain.py実行し、結果は以下のとおりです。

更新リスト[1] 4406700752
GET 4406700920のモジュールが
チェックをすることができます[]

結果を操作わかるように、アドオンで機能をインポートしてのmymoduleない同じモジュール、異なるIDを取得します。もちろん、そのような効果のライン13 main.pyニーズにpython2.7.10で起こり得ます。あなたは誰がライン13本のコードを記述します、求めることができますか?実際には、多くのプロジェクトでは、インポート時間を容易にするためにのsys.pathパイルパスに追加されます。後者の方法は、インポートすることは非常に必要であるとその後のプロジェクトで、私たちは同意します

第九、Pythonのアップグレード

あなたが3.xへ2.xからアップグレードするので、もしpython3.x後方互換性がない、時間は注意する必要があり、ここでは2つです:

python2.7では、戻り値の範囲がリストである。python3.xに、目標範囲のリターン。

マップ()、フィルタ()、dict.items()リストpython2.7を返し、反復子は3.xで返さ もちろん、それらのほとんどは、より良い選択ニシキヘビイテレータであるが、一度だけ横断することができます欠点を持っています。このバグのピットの父が生じたとして共有Instagramのは、とも呼ばれます。

第十、ギル

ギルはPythonでよく認識された欠陥であるので、GILを終了!

引き継ぐために、Pythonのスレッドモジュールが表示されることがあり、他の言語の学生から来て、どのような地獄、ああ、それはスプレーますが、効果がないことがわかりました。

要約:

Pythonは非常に使いやすく、非常に強力な一つの言語である、と言うのは疑いありません。python非常に柔軟で非常に強力なカスタマイズすることができます。同時に、いくつかの罠があり、これらのトラップは、より良い理解は、そのような言語の使用を把握することができます。この記事では、いくつかの欠陥が、これは非網羅的なリストで、追加を歓迎するいくつかのpythonを示しています。

ソース著者:xybaby
出典リンク:www.cnblogs.com/xybaby/p/7183854.html

ます。https://blog.51cto.com/10515215/2405326で再現

おすすめ

転載: blog.csdn.net/weixin_34346099/article/details/91656106