導入
複数のプログラミング言語を学びましたが、ますます混乱してきました。 C 言語では、各変数で変数の型を宣言する必要があり、関数を呼び出すときにパラメーターの型が一貫している必要があることがわかっています。 Python 変数は型を宣言する必要がなく、事前に宣言することさえ許可されていないため、Python はプログラム開発の敷居を大幅に下げます (パフォーマンスは犠牲になります)。この記事では、次の 2 つの問題の解決に焦点を当てます。
- データ型を宣言せずに Python を実装する方法
- Python 言語自体はデザイン パターンを具体化していますか?
この記事では、最初の質問を使用して Python 言語設計の基礎となる実装を検討し、2 番目の質問を使用して Python 言語設計における高レベルの設計パターンのアイデアを検討します。
1.パイソン
Python は C 言語で書かれており、C 言語で書かれた標準ライブラリも多数含まれています。 Python が C 言語を使用する主な理由の 1 つは、C 言語の効率性と移植性です。 Python のオープン ソース コードは GitHub でホストされており、そのウェアハウス アドレスは https://github.com/python/cpython/ です。
1. Python 言語と C 言語の違いは何ですか?
-
構文: Python ではインデント スタイルが使用され、コード ブロックを表すためにコロンが使用されますが、C 言語ではコード ブロックを表すために中かっこが使用されます。
-
タイプ: Python は動的に型付けされた言語であり、実行時にさまざまな変数を動的にバインドできます。 type; C 言語は静的に型付けされた言語ですが、変数の型はコンパイル中に決定されます。
-
自動メモリ管理: Python はメモリを自動的に管理するため、プログラマが手動でメモリを管理する必要はありませんが、C 言語ではメモリの割り当てと解放を含む手動のメモリ管理が必要です。
-
コンパイルと解釈: C 言語は実行前にバイナリ マシン コードにコンパイルする必要がありますが、Python はインタープリタ型言語であり、直接解釈されます。プロセッサーが解釈して実行します。
-
アプリケーション シナリオ: C 言語はオペレーティング システムやコンパイラなどのシステム レベルのアプリケーションの作成に適しており、Python はデータ分析、Web 開発、人工知能などの分野に適しています。
一般に、Python はシンプル学習しやすく、高効率で読みやすい言語に適していますプロトタイプを迅速に開発し、データを処理します。C 言語は低水準言語です。ハードウェアとメモリを直接操作するため、高性能で低レベルのシステム レベルのプログラムを作成するのに適しています。
2. 型を宣言せずに Python を実装するにはどうすればよいですか?
Python は動的に型指定される言語です。変数を使用する前にデータ型を宣言する必要はありません。これは主に次の方法で実現されます:
-
型推論: Python は、コード構文や変数の初期値などの情報を分析することによって、実行時にその型を推論します。これは Python の「自然な」哲学に沿っており、開発者がコードを理解し、保守することも容易になります。
-
メモリを動的に適用する: Python がメモリを適用すると、変数の型に基づいてメモリが動的に割り当てられます。代入中に値の型が変更されると、Python は自動的に元のメモリを解放し、必要なメモリを再適用します。
-
参照カウント: Python は参照カウントを使用して変数のライフ サイクルを追跡します。オブジェクトが参照されるたびに、その参照カウントは 1 ずつ増加します。オブジェクトが参照を失うたびに、その参照カウントは 1 ずつ減分されます。参照カウントが 0 に達すると、Python はオブジェクトによって占有されていたメモリ空間を解放します。
-
オブジェクト モデル:Python ではすべてがオブジェクトであり、コードの実行はオブジェクト間の対話と操作です。したがって、Python の変数はメモリ アドレスではなくオブジェクトを参照するため、ポインタ エラー、メモリ リーク、他の言語で発生する可能性のあるその他の問題を回避できます。
要約すると、Python は、型推論、動的メモリ割り当て、参照カウント、オブジェクト モデルを通じて、変数が型を宣言する必要がないという機能を実現します。
3. Python のすべてがオブジェクトであることをどのように理解すればよいでしょうか?
Python では、「すべてはオブジェクトである」は重要な概念です。これは、数値、文字列、データ構造、関数、モジュールなどを含む Python のすべての要素がオブジェクトとして扱われることを意味します。 「オブジェクト」は、データと動作を含む抽象的な概念です。データはさまざまなタイプの値であり、動作はオブジェクトが実行できるアクションまたは操作です。 Python では、すべてのオブジェクトに型があり、オブジェクトが実行できる操作とサポートするメソッドを定義します。
Python では、すべてのクラスはobject
という名前の基本クラスから継承します。つまり、スーパークラスを指定せずに Python でクラスを定義すると、そのクラスは自動的に object
のサブクラスになります。 object
クラスには、オブジェクトの操作にとって非常に重要な特別なメソッド (「マジック メソッド」とも呼ばれます) がいくつか含まれています。たとえば、 __init__()
メソッドはオブジェクトの初期化に使用され、 __str__()
メソッドはオブジェクトを文字列に変換するために使用され、 __eq__()
メソッドは、2 つのオブジェクトが等しいかどうかなどを比較するために使用されます。
例 1 次のコードを実行します: if (i==0)
C 言語では、上記のコードは条件付きジャンプ命令 (JZ
や JE
など) にコンパイルされ、変数 < をチェックします。 /span>i
の値が 0 に等しいかどうか、等しい場合は if ステートメントにジャンプして実行し、そうでない場合は if ステートメントをスキップします。
Python では、上記のコードはインタプリタによってブール比較演算として解析されます。i==0
、比較の結果に基づいて、コードを実行するかどうかが決定されます。 if ステートメント内のブロック。 Python インタープリターは、 i
と 0
の間のオブジェクトを比較します。つまり、 i.__eq__(0)
を実行し、以下に基づいて if ステートメントを実行するかどうかを決定します。比較結果のコードブロック。
例 2 文字列の連結
C 言語の基本的な実装は比較的原始的であり、文字列は文字配列の形式で存在します。 C 言語では、strcat()
メソッドを使用して文字配列をマージします。マージされた文字列は元の文字配列に直接格納され、新しいメモリ空間が別途開かれることはありません。 C 言語では、文字列結合関数を自分で実装する必要があり、演算子のオーバーロードを直接使用して文字列加算を実装することはできません。
Python 言語では、str = str1+str2
を通じて文字列の結合を直接実行できます。 をオーバーロードする 演算子が使用されます。つまり、 str1 + str2
が実行されると、Python は実際に str1.__add__(str2)
以下は、Python のobject
クラスにおける一般的なマジック メソッドまたは特別なメソッドとその機能の概要です。
魔法の方法 | 関数 |
---|---|
__class__ |
オブジェクトのクラス属性にアクセスするtype() 関数を呼び出します |
__delattr__(self, name) |
オブジェクトのプロパティを削除しようとするときに呼び出されるメソッドを定義します |
__dir__(self) |
オブジェクトに依存しないdir() 組み込み関数呼び出しに応答する方法を定義します。 |
__doc__ |
オブジェクトの docstring を表示します |
__eq__(self, other) |
等価演算子 (==) をサポートします。 |
__format__(self, format) |
文字列のformat() メソッドを使用して、オブジェクトをフォーマットするときに呼び出されるメソッドを定義します |
__ge__(self, other) |
以上演算子 (>=) をサポートします。 |
__getattribute__(self, name) |
ユーザーがオブジェクトのプロパティにアクセスしようとしたときに呼び出されるメソッドを定義します |
__gt__(self, other) |
大なり演算子 (>) をサポートします |
__hash__(self) |
ハッシュ値を返します(整数である必要があります) |
__init__(self[, args...]) |
コンストラクター。オブジェクトの作成時に初期化操作を実行するために使用されます。 |
__init_subclass__() |
このクラスのサブクラス (インスタンスではない) が作成されるときに呼び出されます。 |
__le__(self, other) |
以下演算子 (<=) をサポートします。 |
__lt__(self, other) |
小なり演算子 (<) をサポートします |
__ne__(self, other) |
不等号演算子 (!=) をサポートします。 |
__new__(cls[, args...]) |
オブジェクトを作成し、そのオブジェクトを返すために使用されるメソッド |
__reduce__(self) |
は、pickle モジュール のサポートを提供するために使用されます。 |
__reduce_ex__(self, protocol) |
上記と同じですが、より多くのプロトコルをサポートします |
__repr__(self) |
デバッグに使用される文字列表現 |
__setattr__(self, name, value) |
ユーザーがオブジェクトのプロパティを設定しようとしたときに呼び出されるメソッドを定義します |
__sizeof__(self) |
オブジェクトが占有するメモリバイト数を返します。 |
__str__(self) |
ユーザーはオブジェクトの文字列表現を取得します |
__subclasshook__(cls, subclass) |
サブクラスが継承するときに呼び出され、サブクラスが正当かどうかを確認するために使用されます。 |
これらのメソッドのすべてをオーバーロードして独自のクラスに実装する必要はなく、実際のニーズに応じて選択的に実装できることに注意してください。同時に、Python には他にも多くの組み込み関数と組み込み型があり、それらはすべて独自の特別な用途と一般的なマジック メソッドを持っています。
4.int型
整数型int
を例として、Python の基礎となるメカニズムの説明を続けます。int
は object
__add__(self, other)
: 整数の加算を実装するために使用され、self + other
; と同等です。__sub__(self, other)
: 整数の減算を実装するために使用され、self - other
; と同等です。__mul__(self, other)
: 整数乗算の実装に使用され、self * other
; と同等です。__truediv__(self, other)
: 整数の除算を実装するために使用され、self / other
; と同等です。__floordiv__(self, other)
: 整数の除算を実装するために使用され、self // other
; と同等です。__mod__(self, other)
: 整数モジュロ演算の実装に使用され、self % other
; と同等です。__pow__(self, other[, modulo])
: 整数のべき乗演算の実装に使用され、self ** other
; と同等です。__lshift__(self, other)
: ビット単位の左シフト演算の実装に使用され、self << other
; と同等です。__rshift__(self, other)
: ビット単位の右シフト演算を実装するために使用され、self >> other
; と同等です。__and__(self, other)
:self & other
; と同等のビット単位の AND 演算を実装するために使用されます。__or__(self, other)
: ビットごとの OR 演算の実装に使用され、self | other
; と同等です。__xor__(self, other)
: ビット単位の XOR 演算を実装するために使用され、self ^ other
; と同等です。__invert__(self)
:~self
; と同等のビットごとの反転演算を実装するために使用されます。__index__(self)
:list
、tuple
、dict
これらの組み込み関数により、整数オブジェクトがさまざまな計算や演算をサポートできるようになり、整数データを柔軟に処理できるようになります。
5. メタクラス
Python メタクラス (メタクラス) は、実際にはクラスを作成するために使用されるクラスです。クラスの作成動作と属性を制御して、より高度なオブジェクト指向プログラミングを実現できます。これは、 クラス オブジェクトobject
の親クラスと理解できます。 Python では、メタクラスは非常に重要な概念です。次の属性を通じてクラスの作成と動作を制御できます。
メソッド名 | 説明する |
---|---|
__new__(cls, name, bases, attrs, **kwargs) |
新しいクラスオブジェクトを作成して返すために使用されます |
__init__(self, name, bases, attrs, **kwargs) |
クラス オブジェクトを初期化し、クラス オブジェクトのプロパティとメソッドを変更するために使用されます。 |
__call__(self, *args, **kwargs) |
は、クラス オブジェクトのインスタンス化プロセスをカスタマイズするために使用されます。インスタンスの作成と初期化のプロセスが含まれます。 シングル ケース モード、オブジェクト プールなど、多くの高度なオブジェクト指向プログラミング機能を実装できます。 |
__getattribute__(self, name) |
オブジェクトの属性を取得するために使用されます。メタクラスはこのメソッドをオーバーロードして、属性のアクセス制御と管理を実装できます。 |
__setattr__(self, name, value) |
オブジェクトのプロパティを設定するために使用されます。メタクラスはこのメソッドをオーバーロードして、よりきめ細かいプロパティ設定の制御と管理を実現できます。 |
__getattr__(self, name) |
オブジェクトの存在しない属性を取得するときに呼び出す必要がある関数。メタクラスはこのメソッドをオーバーロードして、属性のデフォルト値、遅延計算などを実装できます。 |
6.Type()関数はクラスを作成します
Python の内部実装では、object
クラスは C 言語で定義されており、そのデータ構造は実際には C 構造体 (struct) であり、オブジェクトの型情報といくつかの特別なフラグ。この C 構造は Python オブジェクト ヘッダーと呼ばれ、次のように定義されます。
typedef struct _object {
_PyObject_HEAD_EXTRA
Py_ssize_t ob_refcnt;
struct _typeobject *ob_type;
} PyObject;
このうち、_PyObject_HEAD_EXTRA
は追加のヘッダー情報を表し、ob_refcnt
はオブジェクトの参照カウントを表し、ob_type
ポイントはオブジェクトに属する型情報、つまりオブジェクトのクラスオブジェクト。
Python では、 クラス自体を含むすべてのオブジェクトの type()
関数を通じてクラス オブジェクトが作成されます。新しいクラスを定義するときは、実際には 関数を通じて新しいクラス オブジェクトを動的に作成し、それをクラスの名前にバインドして、新しいクラスを作成します。例:object
type()
class MyClass:
pass
上記のコードが実行されると、Python インタープリタは自動的に type()
関数を呼び出して MyClass
という名前の新しいクラス オブジェクトを作成し、それを Assigned にバインドします。を変数名 MyClass
に変更し、 MyClass
を使用可能なクラスにします。 type()
関数を使用すると、オブジェクトが属するクラス オブジェクトを確認できます。例:
obj = MyClass()
print(type(obj)) # <class '__main__.MyClass'>
print(type(MyClass)) # <class 'type'>
print(type(object)) # <class 'type'>
出力からわかるように、obj
は MyClass
クラス オブジェクトのインスタンスであり、MyClass
クラス自体は type
クラスによって作成され、 type
クラス自体は object
クラスによって作成されます。 クラス自体も クラスによって作成されます。 a> object
クラスは、Python の最も基本的なクラスです。