連載
» 2019年07月16日 05時00分 公開

Python入門:[Python入門]オブジェクトの同一性、比較、文字列表現 (1/2)

Pythonのオブジェクトの同一性と、is演算子や==演算子による比較の違い、str関数とrepr関数で得られる文字列表現の違いなどについて取り上げる。

[かわさきしんじ,Deep Insider編集部]
「Python入門」のインデックス

連載目次

 前回は、Pythonのオブジェクトがどんなものかについて簡単に見た。今回はオブジェクトの同一性、その比較の仕方、それから文字列表現について見ていく。

オブジェクトの同一性

 前回はオブジェクトは「型」と「値」に加えて「同一性」を持つと述べた。同一性は、コンピュータのメモリ上に作成されたオブジェクトのアドレスのようなものであり、オブジェクトがメモリから取り除かれるまで、変わることはない*1。つまり、オブジェクトが作成されると、それに固有な一意の値が割り当てられる。以下ではこれを「アイデンティティー」と呼ぶことにしよう。

*1 あるオブジェクトが削除された後に、別のオブジェクトが作成されると、それらのアイデンティティーが同じになる可能性はある。が、あるオブジェクトが存在している間は、アイデンティティーを同一にする他のオブジェクトは存在しない。


 オブジェクトのアイデンティティーを調べるには、組み込みのid関数が使える。

id関数

id(obj)


 objのアイデンティティーを示す値を返す。

パラメーター 説明
obj アイデンティティーを調べたいオブジェクト
id関数のパラメーター


 使用例を以下に示す。

mystr = 'Hello'
yourstr = 'Hello'
otherstr = ''.join(['H', 'e', 'l', 'l', 'o'])  # リストから文字列を作成
print(id(mystr))     # 変数mystrが参照している文字列のアイデンティティー
print(id(yourstr))   # 変数yourstrが参照している文字列のアイデンティティー
print(id(otherstr))  # 変数mystr/yourstrが参照している文字列とは別のもの
print('-----')
mylist = [1, 2, 3]     # リストを作成して、変数mylistに代入
yourlist = mylist      # そのリストを変数yourlistに代入
otherlist = list([1, 2, 3])  # mylistと同じ要素を持つリストを作成
print(id(mylist))      # 変数mylistと変数yourlistが参照している
print(id(yourlist))    # オブジェクトは同じなので同じ値になる
print(id(otherlist))   # 同じ要素を持つが別のオブジェクトなので違う値になる

id関数の使用例

 実行結果を以下に示す。

実行結果 実行結果

 変数mystrに代入した文字列'Hello'のアイデンティティーと、変数yourstrに代入した文字列のアイデンティティーを調べた例では同じ値が表示されている。これは2つの文字列オブジェクトと「同一」であることを意味している。一方、変数otherstrには「H」「e」「l」「l」「o」を要素とするリストから文字列を作成したものが代入されている。リストからの文字列の作成により、最初の文字列'Hello'とは別のオブジェクトが作成されたので、変数otherstrが参照している文字列のアイデンティティーは異なるものになっている。

3つの変数が参照するオブジェクトのアイデンティティー 3つの変数が参照するオブジェクトのアイデンティティー

 リストのアイデンティティーの例も同様だ。まず変数mylistに「[1, 2, 3]」というリストを代入している。その後、変数mylistの値を変数yourlistに代入しているので、これらは同一のオブジェクトを参照している。よって、そのアイデンティティーは同一になる。これに対して、変数otherlistに代入されているのは、変数mylist/yourlistが参照しているリストと同じ内容だが、新規に作成したリストだ。そのため、変数otherlistが参照しているリストのアイデンティティーは別のものになっている。

 上の例から分かるのは、値は同じだが、アイデンティティーが異なるオブジェクトが存在するということだ。以下では、これを踏まえて、オブジェクトの比較の方法について見ていこう。

オブジェクトの比較

 オブジェクトを比較する際には、その「アイデンティティー」(同一性)と「値」が重要になってくる。簡単にいえば、2つの変数が同じアイデンティティーを持つオブジェクトを参照していれば、当然のようにそれらは「等しく」なる。だが、アイデンティティーが異なっていても、その「値」が等しいこともある。そのため、Pythonでは次の2種類の比較が行えるようになっている。

  • 同一性:同じアイデンティティーを持っているかを比較
  • 等価性:オブジェクトの値が等しいかどうかを比較

 このうちの同一性を比較するために使われるのが、is演算子とis not演算子の2つだ。前者は2つのオブジェクトが同じアイデンティティーを持っていれば(同じオブジェクトであれば)Trueとなり、後者はその逆だ。

 一方、等価性を比較するのに使われるのが、これまでにも見てきた「==」演算子と「!=」演算子だ。前者は2つのオブジェクトの値が同じであればTrueとなり、後者はその逆だ。

 実際に試してみよう。6つの変数には、先ほどの例と同じ手順で代入をしているので、変数mystr/yourstrは内容もアイデンティティーも同じ、変数otherstrは値だけが同じ。変数mylist/yourlistは内容もアイデンティティー同じ、変数otherlistは値だけが同じとなっている。

mystr = 'Hello'
yourstr = 'Hello'
otherstr = ''.join(['H', 'e', 'l', 'l', 'o'])

mylist = [1, 2, 3]
yourlist = mylist
otherlist = list([1, 2, 3])

print('mystr is yourstr?', mystr is yourstr)
print('mystr is otherstr?', mystr is otherstr)
print('mystr == yourstr?', mystr == yourstr)
print('mystr == otherstr?', mystr == otherstr)

print('mylist is yourlist?', mylist is yourlist)
print('mylist is otherlist?', mylist is otherlist)
print('mylist == yourlist?', mylist == yourlist)
print('mylist == otherlist?', mylist == otherlist)

オブジェクトの比較

 実行結果を以下に示す。

実行結果 実行結果

 上に述べたように、同じアイデンティティーを持つオブジェクト同士(変数mystr/yourstr、変数mylist/yourlist)ではis演算子による比較も、==演算子による比較もTrueとなっているのが分かる。一方、アイデンティティーが異なるが値は等しいオブジェクト同士(変数mystr/otherstr、変数mylist/otherlist)ではis演算子による比較はFalseに、==演算子による比較はTrueになっている。

 なお、「==」演算子はデフォルトでオブジェクトが同一かどうか(同一性)を比較する。組み込み型の一部では、この挙動を置き換えて、値が同じかどうかを比較するようになっている。

 例えば、数値の比較では整数と浮動小数点数でも数学的に正しい比較結果が得られるようになっている。つまり、「1 == 1.0」はTrueとなる(「1 is 1.0」はFalseとなる)。同じ要素で構成される(が、アイデンティティーが異なる)リスト同士を==演算子で比較したときに、Trueとなるのも同様だ。

 なお、文字列やリスト、タプルなどの比較においては、「オブジェクトが同じ型」「要素数が同じ」「同じインデックス位置にある要素同士が同じ」場合に==演算子による比較結果がTrueとなる。

 オブジェクトの比較の詳細については、Pythonのドキュメント「比較」などを参考にしてほしい(本稿では省略したが、順序比較などについても掲載されている)。

オブジェクトの文字列化

 本連載ではここまで、オブジェクトの値を画面に表示するときには、何も気を使うことなく、以下のようなコードを書いていた。

mystr = 'my number is'
mynum = 42
print(mystr, mynum)

mylist = [1, 2, 3]
print(mylist)

オブジェクトの値を画面に出力

 もちろん、実行結果は次のようになる。

実行結果 実行結果

 このときにprint関数はカンマ区切りで並べられたオブジェクトを「文字列化」してから、それを画面に表示している。1つ目のprint関数呼び出しでは、文字列オブジェクトと整数オブジェクトをカンマで区切っているが、これを1つの文字列として表示するなら次のようにしていたところを、これと似たことをprint関数は自動的に行っていてくれたということだ(半角の空白文字はprint関数が引数を出力するときに自動的に補ってくれていたが、それも自分で追加する必要がある)。

print(mystr +' ' + str(mynum))

str関数は整数を文字列に変換してくれる

 第5回「文字列の基本」の「文字列と数値の変換:str/int/float関数」では、整数(int型)や浮動小数点数(float型)の値を文字列に変換するための仕組みとして、str関数を紹介したが、実際にはこれはオブジェクトの「文字列表現」(オブジェクトを文字列化したもの)を返す関数だ。

str関数

str(obj)


 objの文字列表現を返す。

パラメーター 説明
obj 文字列化したものを得たいオブジェクト
str関数のパラメーター


 print関数のドキュメントには「キーワードなしの引数はすべて、 str() がするように文字列に変換され」とある。つまり、print関数にオブジェクトを渡すと、それらをstr関数で文字列化したものが表示されるということだ。よって、「print([1, 2, 3])」のようにリストをprint関数に渡すと、リストそのものではなく、それを文字列化したものが表示される。

 しかし、Pythonにはオブジェクトを文字列化するもう1つの手段がある。それが組み込みのrepr関数だ。

repr関数

repr(obj)


 objをPythonにとって意味のある文字列表現として返す。

パラメーター 説明
obj Pythonにとって意味のある文字列表現を得たいオブジェクト
repr関数のパラメーター


 試しに幾つかのオブジェクトをstr関数とrepr関数で文字列化してみよう。

print('str(1):', str(1))
print('repr(1):', repr(1))
print('str([1, 2, 3]):', str([1, 2, 3]))
print('repr([1, 2, 3]):', repr([1, 2, 3]))
print('str("Hello"):', str("Hello"))
print('repr("Hello"):', repr("Hello"))

str関数とrepr関数の使用例

 この結果は次のようになる。

実行結果 実行結果

 結果はほぼ変わらないが、最後の2つの出力にだけ微少な(しかし大きな)違いがある。str関数で文字列'Hello'を文字列化(これは、実際には文字列そのものが戻り値となる)したものにはシングルクオート「'」がないが、repr関数の方の出力ではシングルクオートが付加されている点がそうだ。

 そこで文字列表現を得るこれら2つの関数の差について次に考えてみよう。

       1|2 次のページへ

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。