はじめに
ハッカソンでPythonを使うことになったのでPythonの基礎を勉強していたのですが、途中でオブジェクトがインスタンスを内包していてもその逆があるのかが分からなくなりました。現在は「結論」で解決済みですが、本記事はその経緯を記したものです。
chatGPTに聞きながらドキュメントや記事等で裏取りをしていく流れで調べていったため、裏取り漏れで間違っている部分がある可能性があるため参考にされる方はご注意ください🙇♂️
まず結論
Pythonでの扱いとしてはインスタンス
=オブジェクト
です。つまりPythonでは、オブジェクトである以上それはインスタンスだし(クラスから生成されている)、当然インスタンスである以上オブジェクトです。
当然意味はイコールではありません。
オブジェクト:メモリ上に存在するデータの実体**
インスタンス:クラスによって生成されたオブジェクト
Pythonでは全ての値がクラスから生成され、メモリ上に割り当てられているということになります。
概念整理
Pythonにおけるオブジェクト・クラス・インスタンス
この3つの理解はいろんな説明を列挙した方が理解しやすいと思ったので列挙。
オブジェクト
- 個性として存在してる実体。
- メモリ上に存在してる値は全てオブジェクト。
- オブジェクトは必ずメモリ上に実態として存在している。
- 値が格納された変数自身は、オブジェクトではなく参照である。
-
a=1
なら、1
がオブジェクトでa
はそのオブジェクトを指すだけ。
-
- 全てのオブジェクトは、必ず何かしらのクラスのインスタンスである。
-
脱線:
- Pythonの場合、
a=1
の1はint型になるが、これはintクラスで1
というインスタンスを生成しているということ(intなどの型は実際にはCでクラス的な振る舞いになるように実装している)。- Pythonでは
class クラス名:
という記述の中にコンストラクタを直接定義してクラスという機能を実装する。一方でCはオブジェクト指向言語ではないので、クラスのような機能は手動で実装する必要がある。具体的には構造体というただの入れ物を作って別途初期化関数を呼ぶ。 - Pythonではコードのパース時に
1
という数字リテラルを見つけると、すぐにそれを対応するクラスのインスタンスとして生成されている。 - Cで定義したint的な振る舞い(構造体)を
"int"
というリテラルでクラスとして呼び出せるように定義している部分→cpython/Objects/longobject.cの6616行目- 構造体(Pythonでのintクラスのインスタンスをどういう構造にするか定義する役目):
PyLongObject
- 初期化関数(コンストラクタ):
long_new
- 構造体(Pythonでのintクラスのインスタンスをどういう構造にするか定義する役目):
- Pythonのint的な振る舞いを定義している部分:
PyLongObject
は元の名前が_longobject
っぽかったのでここから潜れば見れそうだけどそこまでの理解はしなくても良い気がした。
- Pythonでは
- Pythonでは
print(type(int))
を実行すると<class 'type'>
と出力される。つまり、int
もまたtype
クラスのインスタンスということになる→Pythonではintやstrなどの型もオブジェクトとして扱っている(メタクラス構造と言うらしい)。
- Pythonの場合、
クラス
- 設計図のこと。
- オブジェクトをインスタンス化するためのもの。
記述方法:nameという属性を持つPersonの設計図
class Person:
def __init__(self, name):
self.name = name
インスタンス
- クラスから生成したオブジェクト(実体)。
p = Person("Alice")
さっきの設計図出でてきた以下の部分はコンストラクタというもの。コンストラクタとは、オブジェクトを生成する時に呼び出される関数。
def __init__(self, name):
self.name = name
このクラスPersonを定義し、
p = Person("Alice")
とすることで、Personクラスのコンストラクタ関数が呼び出され、self.name = name
で p.name
が "Alice"
に設定される。
不明点(本題)←解決済み
Pythonにおけるオブジェクトとインスタンスの違いについて色々と調べていると、 >インスタンスはオブジェクトの1種だけど、オブジェクトは必ずしもインスタンスであるとは限らないという記述を結構見るので、これまでの整理を基準にするとPythonではインスタンスとオブジェクトは同値的な関係っていう事になるので、そもそも前提が違うのかも知れない。
正しい結論として考えられる候補としては以下の3つ...?
- Pythonに限りインスタンス=オブジェクトで、別の言語ではオブジェクトはインスタンスを内包しその逆はないという関係が成立している。
- Pythonでは自作クラスにより生成されたオブジェクトのみインスタンスと呼び、intのようなCによってクラスとして実装された型で生成されたオブジェクトはインスタンスとは呼ばないという慣習的なもの。
- Pythonのintのような型がPythonの内部実装でクラスとして実装されいてるという前提が違う(読み間違えている)。
結論が絞れても、どの結論が正しいかを証明するための知識が何かが現状分かっていないので、勉強していく中で気づいたら改めて調べてみようと思った。
結論
Pythonでは全てのデータが何らかのクラスのインスタンスとして実装されています。type(値)とすれば対応する型(クラス)と出力され、どのクラスでインスタンス化されているかを確認できます。
さいごに
恐らく基本的なCSの知識が欠如してるから抽象から具体に理解を進めようとして、その結果わけ分からなくなってる気がしたので今後はしっかりCSの勉強もしないといけないなと思いました。
参考
オブジェクト指向プログラミング言語トップ6
3. データモデル/3.1. オブジェクト、値、および型
9. クラス
オブジェクトとインスタンス
python/cpython
C言語とは!特徴やC++やC#との違いを分かりやすく解説
pythonで考えるメタクラスとは?
第31回 オブジェクトとクラスとは?インスタンスとオブジェクトの違いも含めてざっくりイメージしてみた (菱沼佑香)