# オブジェクトってなに?
このページでは、オブジェクトの「仕組み」、 「どうやって動いているか」というちょっと厄介な話について取り扱います。
全力で頑張って書いてはいますが Python を習いたての方には、 抽象的過ぎてあまり面白くないかもしれません。
class を使ったオブジェクトの具体的な「考え方」や「使い方」を知りたいという方は、 霧島京子先生に教えてもらうといいかもしれません。
では、ここから先は、オブジェクトの「仕組み」、 「どうやって動いているか」というちょっと込み入った話について考えていきたいと思います。
# オブジェクトって具体的になに?
インスタンス化されたもの
>>> # インスタンスオブジェクト
>>> girl_friend = GirlFriend('サーバルちゃん')
>>>
あるいは
例えば、整数 1
, 文字列 'Hello, world!'
, リスト [1,2,3]
は変数に代入できます。
このことから、整数 1
, 文字列 'Hello, world!'
, リスト [1,2,3]
は、
インスタンスオブジェクトであることがわかります。
# 変数に代入できるものは
# インスタンスオブジェクト
a = 1
b = 'Hello, world!'
c = [1, 2, 3]
>>> # 変数に代入できるものは
>>> # インスタンスオブジェクト
>>> a = 1
>>> b = 'Hello, world!'
>>> c = [1, 2, 3]
>>>
# ◯ リテラルもオブジェクト
もしかしたら「整数 1
がインスタンスオブジェクトです。」と言われても、
別にインスタン化している訳ではないので、いまいちピンと来ないかもしれません。
# 対話モード >>> に
# コピペで実行できます。
class クラス:
pass
# インスタンス化
インスタンス = クラス()
変数に代入する以外にも何かインスタンスオブジェクトであるかどうか確認する方法はないでしょうか? 実は、インスタンスオブジェクトを使えば、「属性の参照」ができます。
ところで、インスタンスオブジェクトを使うと何ができるのでしょうか? インスタンスオブジェクトが理解できる唯一の操作は、属性の参照です。
9.3.3. インスタンスオブジェクト - Python チュートリアル (opens new window)
そこで実際に属性の参照ができるかどうかをみて、
整数 1
がインスタンスオブジェクトであるかどうかを確認して見たいと思います。
# 整数 1 はインスタンスオブジェクト
a = 1
# だから、属性の参照ができる。
# a の実部
a.real
# a の虚部
a.imag
>>> # 整数 1 はインスタンスオブジェクト
>>> a = 1
>>>
>>> # だから、属性の参照ができる。
>>> # a の実部
>>> a.real
1
>>>
>>> # a の虚部
>>> a.imag
0
>>>
正確には属性とは違いますが、 同様に文字列 str も自分自身を構成するオブジェクトを参照することができます。
b = 'Hello, world!'
b[0]
b[1]
b[2]
>>> b = 'Hello, world!'
>>> b[0]
'H'
>>> b[1]
'e'
>>> b[2]
'l'
>>>
# ◯ まとめ
1
や 'Hello, world!'
といったリテラルもオブジェクトだということがわかりました。
さらに、リテラル自身もオブジェクトの集まりによって表現されていることがわかりました。
Python の作者である Guido van Rossum のブログを引用します。
Python における私の目標の一つが、 すべてのオブジェクトを 「ファーストクラス」 にするというものであった。
これは、プログラミング言語の中のすべてのオブジェクト(数値、文字列、関数、クラス、モジュール、メソッドなど)に対して、 名前をつけて、同じように取り扱うことができるようになるということを意味している。
オブジェクトを変数に格納したり、リストの中に並べたり、辞書に格納したり、 引数として渡したり、といったことが可能になるのである。
すべてをファーストクラスに - The History of Python.jp (opens new window)
ファーストクラス、第一級オブジェクトとは、ざっくり言えば、 変数に代入できるものです。
第一級オブジェクト - Wikipedia (opens new window)
第一級オブジェクト(ファーストクラスオブジェクト、first-class object)は、 あるプログラミング言語において、 たとえば生成、代入、演算、(引数・戻り値としての)受け渡しといった その言語における基本的な操作を制限なしに使用できる対象のことである。
# オブジェクトは辞書の集まり
頑張ればユーザ定義クラス class とほぼ同等のことを 辞書 dict で実装することができます。
組み込み関数に getattr (opens new window), setattr (opens new window) というものがあります。
class User:
pass
user = User()
# user.name = '岩倉玲音'
setattr(user, 'name', '岩倉玲音')
# user.name
getattr(user, 'name')
>>> getattr(user, 'name')
'岩倉玲音'
>>>
getattr, setattr が取る引数を辞書に書き換えて class と同じことを実装して遊んでました。 以下のコードは一切、見る必要はありません。
# 組み込み関数 getattr, setattr を...
getattr(ユーザ定義クラスのインスタンス, 属性の名前)
setattr(ユーザ定義クラスのインスタンス, 属性の名前, 属性に代入するオブジェクト)
# 辞書を引数に取るように書き換えて遊んでました。
getattr_(辞書, 属性の名前)
setattr_(辞書, 属性の名前, 属性に代入する辞書)
なにが言いたいのかというと、 「dict を組み合わせると class と同じことができます」と言うことです。
オブジェクトは辞書を組み合わせて作られています。 これはたとえ話とかではなくて、実際に本当にオブジェクトは辞書を組み合わせて実装されています。 本当にそうであることを、このさき順番を追って見ていきます。
# オブジェクトを構成する3つのもの
1. class, 型
2. identity, 同一性
3. value, 値
すべてのオブジェクトは、同一性 (identity)、型、値をもっています。
Every object has an identity, a type and a value.
3.1. オブジェクト、値、および型 - Python 言語リファレンス (opens new window)
型は type 関数 (opens new window) で、 同一性は id 関数 (opens new window) で取得できます。 しかし 値 は取得できません。まずは値は、属性くらいに考えておいて下さい。
値は Python ではやや抽象的な概念です: 例えば、オブジェクトの値にアクセスする正統な方法はありません。
6.10.1. 値の比較 - Python 言語リファレンス (opens new window)
簡単なサンプルコードを示します。
# 対話モード >>> に
# コピペで実行できます。
class GirlFriend:
def __init__(self, name):
self.name = name
girl_friend = GirlFriend('岩倉玲音')
# 1. identity, 同一性
id(girl_friend)
# 2. class, 型
type(girl_friend)
# 3. value, 値(いまは属性くらいに思っていてください)
girl_friend.name
>>> # 1. identity, 同一性
... id(girl_friend)
4520026352
>>>
>>> # 2. class, 型
... type(girl_friend)
<class '__main__.GirlFriend'>
>>>
>>> # 3. value, 値
... girl_friend.name
'岩倉玲音'
>>>
ここからは identity 同一性, class クラス, value 値 の3つを見ていきたいと思います。
「クラスってなに?」で、オブジェクトが辞書の集まりであることを見ていきます。 あとの「同一性ってなに?」、「値ってなに?」は、Python の内部の実装を見るきっかけになればと思っています。
# 1. class クラス
>>> type(girl_friend)
<class '__main__.GirlFriend'>
>>>
# 2. identity 同一性
>>> id(girl_friend)
4520026352
>>>
# 3. value 値
>>> girl_friend.name
'岩倉玲音'
>>>
# まとめ
と言うことを、見ていきます。