1
0

Python の dict のキー 1.0 と 1 は同一視される(そして True も!)

Last updated at Posted at 2024-03-25

Python のキーで、int と float、つまり整数と浮動小数点は同一視されるようでした。たとえば 1.0 と 1 は同一視されるようです。仕組みは、謎です。

コード

a = {}
a[1] = 100
a[1.0] = 200
print(a) # => {1: 200}

キーは最初に指定した値が採用されるようです。

b = {}
b[1.0] = 300
b[1] = 400
print(b) # => {1.0: 400}

__hash__ の値を見てみましょう。

(123).__hash__() # => 123
(123.0).__hash__() # => 123
(123.456).__hash__() # => 1051464412201451643

なるほど! 驚きですね!

Python 3.5 のドキュメントに書いてありました。

Numeric values that compare equal have the same hash value (even if they are of different types, as is the case for 1 and 1.0).

詳しい説明も見つけたので貼っておきます。

感想

Python では 1 == 1.0 が成立するので、dict のキーにおいて 1.0 と 1 が同一視されるのは合理的な気もしますね。こういった言語に触れたことがあまりなかったので、個人的には新鮮でした。

※追記

コメントで指摘いただきましたが、True / False も 1 / 0 と同一視されるそうです。@shiracamus さんありがとうございます。

以下の記事で詳しく説明されています。

a = {};
a[1] = 100
a[1.0] = 200
a[True] = 300
print(a)               # => {1: 300}
print(1 == True)       # => True
print(True.__hash__()) # => 1
a = {};
a[0] = 100
a[0.0] = 200
a[False] = 300
print(a)                # => {0: 300}
print(0 == False)       # => True
print(False.__hash__()) # => 0

※追記2

そんな馬鹿なと思ったのですが、Fraction と Decimal もそうらしいです。

from fractions import Fraction
from decimal import Decimal

a = {}
a[1] = 100
a[1.0] = 200
a[True] = 300
a[Fraction(999, 999)] = 400
a[Decimal(1)] = 500
print(a) # => {1: 500}

1
0
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0