この一連の記事は、「Pythonプログラムを改善するための高品質なコード91の提案を書く」の本質の要約です。
モジュールのインポートについて
外部モジュールのPythonを導入する3つの方法:import
文、from ... import ...
および__import__
機能。最初の2つはより一般的です。
使用時にはimport
、それに注意を払う必要があります:
- 優先順位の使用
import A
またはimport A as a
- 控えめに使う
from A import B
- 使用しないようにしてください
from A import *
以下のためのfrom a import ...
制御されていない使用の問題は、持参する場合は、:
- 名前空間の競合
- ネストされたループのインポートの問題(2つのファイルが互いの変数または関数またはクラスをインポートする)
i += 1
等しくない ++i
Pythonインタプリタがあろう++i
ものとして解釈される+(+i)
場合、+
記号の正の数を表します。以下のためには--i
似ています。
したがって、我々は理解しなければならない++i
文法レベルPythonは有効ですが、通常の意味ではないインクリメント演算子。
使用するwith
自動シャットリソースを
開いたファイルはシステムリソースを占有するだけでなく、他のプログラムやプロセスの動作に影響を与える可能性があるため、ファイル操作が完了したらすぐにそれらを閉じる必要があります。また、ユーザーの期待と実際の操作結果との不一致が発生する場合もあります。
Pythonは、構文を伴うwithステートメントを提供します。
with 表达式 [as 目标]:
代码块
withステートメントはネストをサポートし、複数のwith句をサポートし、それらは相互に変換できます。with expr1 as e1, expr2 as e2
次のネストされたフォームと同等です。
with expr1 as e1:
with expr2 as e2:
使用else
句を簡素化ループ(例外処理)
サイクルでは、else
句は、サイクルによってか暗示を提供break
サイクル判決文の終わりに起因します。例:
# 以下两段代码等价
# 借助了一个标志量 found 来判断循环结束是不是由 break 语句引起的。
def print_prime(n):
for i in range(2, n):
found = True
for j in range(2, i):
if i % j == 0:
found = False
break
if found:
print("{} is a prime number".format(i))
def print_prime2(n):
for i in range(2, n):
for j in range(2, i):
if i % j == 0:
break
else:
print("{} is a prime number".format(i))
ときサイクル「自然」終了(ループ条件が偽である)else
句は、一度実行され、サイクルがあるときにbreak
、割り込み文、else
句は実行できません。
そして、for
文と類似while
文else
句の意味は同じである:else
ブロックが満たされていない通常のサイクルとサイクル条件の終了時に実行されます。
例外処理のいくつかの基本原則に従います
Pythonは、一般的に例外処理の構文で使用されるtry
、、 、、except
彼らは様々な組み合わせを持つことができます。構文は次のとおりです。else
finally
# Run this main action first
try:
<statements>
# 当 try 中发生 name1 的异常时,进行处理
except <name1>:
<statements>
# 当 try 中发生 name2 或 name3 中的某一个异常时
except (name2, name3):
<statements>
# 当 try 中发生 name4 的异常时处理,并获取对应实例
except <name4> as <data>:
<statements>
# 其他异常时,进行处理
except:
<statements>
# 没有异常时,执行
else:
<statements>
# 无论有没有异常,都执行
finally:
<statements>
例外処理には通常、次の基本原則が必要です。
- お勧めできません
try
あまりにも多くのコードを配置。試行に多くのコードを配置することによって引き起こされる問題は、プログラムで例外がスローされると、見つけにくくなり、デバッグと修復が不便になるため、例外をスローする可能性のあるステートメントブロックの前にのみ配置するようにしてください。ステートメントを試してください。 - 慎重な使用別々の
except
文は、すべての例外を処理する、それが特定の例外を見つけることが最善です。また、使用することを推奨していないexcept Exception
か、except StandardError
キャッチ例外に。あなたが使用する必要がある場合、それを使用するのが最適であるraise
上位層に渡された例外をスローするステートメントを。 - 例外のキャッチの順序に注意を払い、適切なレベルで例外を処理します。
- ユーザーは、組み込みの例外から継承して独自の例外クラスを作成することもできます。これにより、組み込みクラスの継承構造が拡張されます。この場合、例外がキャプチャされる順序は非常に重要です。より正確には、エラーの原因を見つけるために、推奨されるアプローチは、前に中性子の異常を継承することで
except
、後続の例外でthrowステートメント、親クラスexcept
スロー声明。この理由は、ときにあるtry
ブロックが発生した例外を有する、インタプリタに応じてexcept
即座に例外を処理容易最初の試合で宣言の順序と一致します。 - 例外をキャッチする順序は非常に重要です。同時に、例外は適切な場所で処理する必要があります。1つの原則は、例外をキャッチした場所で処理できる場合は、タイムリーに処理することです。上位層に渡す場合は、異常がなくなった場合に注意する必要があり、パラメータなしでレイズを使用して渡すことができます。
- ユーザーは、組み込みの例外から継承して独自の例外クラスを作成することもできます。これにより、組み込みクラスの継承構造が拡張されます。この場合、例外がキャプチャされる順序は非常に重要です。より正確には、エラーの原因を見つけるために、推奨されるアプローチは、前に中性子の異常を継承することで
- よりわかりやすい例外情報を使用し、例外パラメーターの仕様に従ってください。一般的に、異常なリーダーには、ソフトウェアを使用するものとソフトウェアを開発するものの2種類があります。
最終的に可能なトラップを回避
かかわらずtry
例外が声明を投げているかどうか、finally
文は常に実行されます。この機能のため、finally
クリーンアップ作業を行うためにステートメントがよく使用されます。
しかし、使用finally
時には、トラップ特に注意する必要があります。
- ときに
try
例外がブロック内で発生した場合、except
ステートメントを処理する対応する例外を見つけることができません、例外は一時とき、アップ保存されるfinally
時間が終了すると、一時的な保存に例外を再びスローされますが、場合finally
文が生成されます新しい例外または実行return
やbreak
、文、一時的に保存された例外が異常なシールドで、その結果、失われます。 - 実際のアプリケーション開発プロセスでは、推奨されていません
finally
使用するreturn
このアプローチは誤解をもたらすだけでなく、非常に重大なミスにつながる可能性があり、リターンに声明を。
どれも深く理解し、オブジェクトが空かどうかを正しく判断する
Pythonの次のデータは空として扱われます。
- 一定
None
- 一定
False
- このようなゼロ値型のいずれかの形態、
0
、0L
、0.0
、0j
- 以下のような空のシーケンス、
''
、()
、[]
- 次のような空の辞書
{}
- ユーザ定義のクラスが定義されている場合
__nonzero__()
と__len__()
方法、及び方法は、整数を返し0
又はFalse
時間。
if list1 # value is not empty
Do something
else: # value is empty
Do some other thing
- これは、実行時に内部メソッドを呼び出して
__nonzero__()
変数を決定するためにlist1
nullであり、結果を返します。
注:
__nonzero__()
メソッド-この内部メソッドは、独自のオブジェクトのnull値をテストするために使用され、0/1またはTrue / Falseを返します。
- オブジェクトは、メソッドを定義しない場合、Pythonは取得
__len__()
メソッド呼び出しの結果を判断します。__len__()
戻り値0は空を意味します。クラスが定義されていない場合は__len__()
方法が定義されていない__nonzero__()
方法を決意結果が真である場合、クラスの例が使用されます。
文字列の形式を使用してみてください.format
ではなく、%
利用するように推奨format
代わりの方法%
文字列形式、理由オペレーター:
-
format
使用に比べて実施例%
より柔軟なオペレータ。使用format
時にモード、および順序は、必ずしも同一の書式設定パラメータではありません -
format
メソッドはパラメータとして簡単に渡すことができますweather = [("Monday", "rain"), ("Tuesday", "sunny"), ("Wednesday", "sunny"), ("Thursday", "rain"), ("Friday", "cloudy")] formatter = "Weather of '{0[0]}' is '{0[1]}'".format for item in map(formatter, weather): print(item)
-
%
最終的には.formatに置き換えられます。公式Pythonドキュメントによると、理由は残る%
オペレータは、下位互換性を維持することです -
%
以下のために、いくつかの特別なケースでの方法を使用する場合には、特別な注意が必要とされている%
文字自体がタプルであるならば、あなたが使用する必要があり、このフォームの直接文字書式%
を使用して(itemname,)
、回避エラーするためにこのフォームをカンマに注意してください。
可変オブジェクトと不変オブジェクトを別々に扱う
Pythonのすべてがオブジェクトであり、オブジェクトは、値を変更できるかどうかに応じて、可変オブジェクトと不変オブジェクトに分けられます。
-
不変オブジェクト
- 数字
- 文字列
- タプル
-
可変オブジェクト
- 辞書
- リスト
- バイト配列
関数のデフォルトパラメータとして変数オブジェクトを使用する場合は特に注意してください。変数オブジェクトを変更すると、元のオブジェクトに直接影響します。
最善の方法は、渡されたNone
オブジェクトを作成するときに、デフォルトのパラメータは、動的に生成された変更可能なオブジェクトとして。
-
可変オブジェクトの場合、スライス操作は浅いコピーと同等です。
-
不変オブジェクトの場合、それに関連する操作を実行しても、Pythonは実際には元の値を保持し、新しいオブジェクトを再作成するため、文字列オブジェクトをインデックスで割り当てることはできません。同時に2つのオブジェクトがある場合文字列オブジェクトを指す場合、オブジェクトの1つに対する操作は他のオブジェクトには影響しません。
パラメータを渡す関数は値でも参照でもありません
Pythonの関数にパラメーターを渡す方法は、値でも参照でもありません。
これは、正しい名前であるべき転送オブジェクト(オブジェクトによる呼び出し)または基準質量オブジェクト(コール・バイ・オブジェクト参照 )。
関数パラメーターは、渡すプロセスでオブジェクト全体を渡します。
- 以下のために可変オブジェクト:その変形は、発呼者と被呼者との間でこのオブジェクトを共有し、内部および外部関数に表示され
- 不変オブジェクト:実際には変更されないので、そのため、多くの場合、新しいオブジェクトを作成することによって変更された後、達成するために割り当てられ、
注意して可変長パラメーターを使用する
*args, **kwargs
次の理由により、可変長パラメーターを注意して使用してください。
- 使用するには柔軟性が高すぎます。可変長パラメーターは、この関数のシグニチャーが十分に明確ではないことを意味し、呼び出しには多くの方法があります。さらに、可変長パラメーターはプログラムの堅牢性を損なう可能性があります。
- 関数のパラメータリストが非常に長い場合に使用しても、
*args
および**kwargs
関数の定義が、通常この機能を簡素化するために、より良い実装を持つことができ、それが再構築されなければなりません。たとえば、タプルと辞書を直接渡すことができます。
可変長パラメーターは、以下の状況での使用に適しています。
- 関数にデコレーターを追加する
- パラメーターの数が不明な場合は、可変長パラメーターの使用を検討してください
- 関数のポリモーフィズムを実装するため、または継承の場合にサブクラスが親クラスのいくつかのメソッドを呼び出す必要がある場合に使用されます
深い理解str()
とrepr()
区別
関数str()
とrepr()
Pythonはオブジェクト文字列に変換することができ、両方を使用して出力が非常に類似しています。以下の違いがあります。
-
2つの目標は異なります。
str()
主にユーザー向けで、その目的は読みやすさです。戻りフォームは、使いやすさと読みやすさを備えた文字列型です。- そして
repr()
開発者のために、精度の目的は、Pythonインタプリタの内部の意味を示す戻り値は、デバッグのために使用さ
-
デフォルトは、入力に直接インタープリタで呼ばれている
repr()
機能、およびprint
その後、呼び出しstr()
機能を -
repr()
戻り値は、一般的にできるeval()
オブジェクトを復元するために機能します。通常、次の方程式があります。obj == eval(repr(obj))
-
一般的に、クラスが定義されなければならない
__repr__()
方法、および__str__()
方法を可読性が精度よりも重要であるとして、任意であり定義されたと考えるべきである__str__()
方法。クラスが定義されていない場合__str__()
、デフォルト使用して、メソッドを__repr__()
オブジェクトの文字列表現を返すために、プロセスの結果を。ユーザが達成する__repr__()
時間法を、戻り値を使用することができることを保証することが望ましいeval()
オブジェクトが再び復元される方法。
静的メソッドとクラスメソッドの該当するシナリオを区別する
静的メソッド:
class C(object):
@staticmethod
def f(arg1, arg2, ...):
クラスメソッド:
class C(object):
@classmethod
def f(cls, arg1, arg2, ...):
类名.方法名
またはからアクセスできます实例.方法名
。
その中でも、静的メソッドには、バインディング、バインド解除、暗黙的なパラメーター、その他のルールなど、従来のメソッドの特別な動作はありません。クラスメソッドの呼び出しは、クラス自体を暗黙的なパラメーターとして使用しますが、呼び出し自体はパラメーターを明示的に提供する必要はありません。
クラスメソッド
- 呼び出し時に明示的なclsの宣言はありませんが、実際にはクラス自体が非表示パラメーターとして渡されます
- クラスメソッドは、基本クラスまたはサブクラスのどちらを介して呼び出されるかを決定できます。
- クラスメソッドがサブクラスによって呼び出されると、基本クラスの代わりにサブクラスの属性を返すことができます
- クラスメソッドがサブクラスによって呼び出されると、サブクラスの他のクラスメソッドを呼び出すことができます
静的メソッド
- 特定のインスタンスにも特定のクラスにも関連していない
- クラスで静的メソッドが定義されている理由は、コードをより効率的に編成できるため、関連するコードの垂直距離が近くなり、コードの保守性が向上するためです。
この記事は最初に公開アカウントで公開されました[Pythonとアルゴリズムへの道]