質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

オブジェクト

オブジェクト指向において、データとメソッドの集合をオブジェクト(Object)と呼びます。

データバインディング

データソースと、アプリケーションやウェブページ(ウェブアプリケーション)のユーザインタフェースを静的または動的に結合する技術です。

データ構造

データ構造とは、データの集まりをコンピュータの中で効果的に扱うために、一定の形式に系統立てて格納する形式を指します。(配列/連想配列/木構造など)

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

3回答

1928閲覧

組み込みデータ型の親クラスになっているobjectとはなんなのか

sequelanonymous

総合スコア123

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

オブジェクト

オブジェクト指向において、データとメソッドの集合をオブジェクト(Object)と呼びます。

データバインディング

データソースと、アプリケーションやウェブページ(ウェブアプリケーション)のユーザインタフェースを静的または動的に結合する技術です。

データ構造

データ構造とは、データの集まりをコンピュータの中で効果的に扱うために、一定の形式に系統立てて格納する形式を指します。(配列/連想配列/木構造など)

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

2クリップ

投稿2021/04/29 06:24

下記のように組み込みデータ型の親クラスは、objectになります。

python

1>>> for i in int, float, str: 2... print(i.__bases__) 3... 4(<class 'object'>,) 5(<class 'object'>,) 6(<class 'object'>,)

objectクラス内を覗いてみると__float__はありません。

python

1>>> dir(float.__bases__) 2['__add__', '__class__', '__class_getitem__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'count', 'index'] 3>>>

そのため、objectクラスの__float__()にアクセスしようとすると、当然ないのでアクセスできません。

python

1>>> class Test: 2... def base_class(self): 3... print(super().__float__) 4... print(super()) 5... print(dir(super())) 6... return "OK" 7... 8>>> t1 = Test() 9>>> t1 10<__main__.Test object at 0x107e0abe0> 11>>> t1.base_class() 12Traceback (most recent call last): 13 File "<stdin>", line 1, in <module> 14 File "<stdin>", line 3, in base_class 15AttributeError: 'super' object has no attribute '__float__'

一方で、floatを継承して親クラスを確認してみると、floatクラスではなく、objectクラスが親クラスになっているようにもみえます。そして、objectクラスの__float__()を呼び出しているようにみえます。

floatクラスを明示的に継承してるはずなのに、なぜprint(super())の結果にfloatクラスが含まれていないのか理解できないので、ご存知のかた教えていただけませんでしょうか?

python

1>>> class Test2(float): 2... def base_class(self): 3... print(super().__float__()) 4... print(super()) 5... print(dir(super())) 6... return "OK" 7... 8>>> t2 = Test2() 9>>> t2 100.0 11>>> t2.base_class() 120.0 13<super: <class 'Test2'>, <Test2 object>> 14['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__self__', '__self_class__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__thisclass__'] 15'OK'

しかし、__bases__で確認すると親クラスは、floatになっていますが、__float__は存在しません。
だとすると、上記のコードでsuper().__float__()__float__()にアクセスできている理由の意味が全くわかりません。
また、上記のコードでは、継承されていないようにみえたのに__bases__だと継承されてることがわかるのが理解できません。

python

1>>> Test2.__bases__ 2(<class 'float'>,) 3>>> dir(Test2.__bases__) 4['__add__', '__class__', '__class_getitem__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'count', 'index']

以上から、組み込み型のfloatは、クラスなので下記のようにbuiltin scope内で定義されているだろうという仮説がたちますが、実際には、どうやらそういった実装にはなっていないようにみえます。

python

1class object: 2 def __init__(): 3 ... 4 5class float(object): 6 ... 7 def __float__(): 8 ...

では、改めてfloatの親クラスをみてみますが、objectになっています。さて、このobjectは、何者なんでしょうか?floatとなんの関係があるのでしょうか? __float__()は、一体どこのクラス内に定義されたスペシャルメソッド、スペシャル属性なのでしょうか?

python

1>>> float.__bases__ 2(<class 'object'>,)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

quickquip

2021/04/29 07:21

> 一方で、floatを継承して親クラスを確認してみると、floatクラスではなく、objectクラスが親クラスになっているようにもみえます。そして、objectクラスの__float__()を呼び出しているようにみえます。 何を見て「みえます」と言っているのか不明でした。
guest

回答3

0

質問に

組み込み型のfloatは、クラスなので下記のようにbuiltin scope内で定義されているだろうという仮説がたちますが、実際には、どうやらそういった実装にはなっていないようにみえます。

python

1class object: 2 def __init__(): 3 ... 4 5class float(object): 6 ... 7 def __float__(): 8 ...

とありますが、ここがおかしいです。
なっていないようにみえるという認識の方が間違っています
そしてどうして認識を間違っているのか? どのようにして間違えているのか? が他の人からは理解できません。
そこで話が食い違います。
質問者さんの認識を、あるいは質問者さんの頭の中にだけ存在する実行モデルを、改める手助けになるように「実際こう動いていますよ」という回答をしています。というか他人からはそれしかできません。
なのに質問者さんは「自分の頭の中にだけ存在する実行モデル」を改めようとしないので話が食い違います。
そういう状況かと思っています。


「実際こう動いていますよ」という(別の)回答をしていきましょう。それしかできませんから。
イメージとしてはこんな実装になっていると想像したらいいと思います。
... の部分は全部C言語で実装されている何かだと考えておきましょう。

python

1class object: 2 def __init__(self): 3 ... 4 # object に __float__ はない 5 6class float(object): 7 ... 8 def __float__(self): 9 # floatは変換するまでもなくfloatだから自分自身を返せばいい 10 return self 11 12class str(object): 13 ... 14 def __float__(self): 15 ... 16 17 18class bytes(object): 19 ... 20 def __float__(self): 21 ... 22 23class int(object): 24 ... 25 def __float__(self): 26 ... 27 28def float(x): 29 return x.__float__()

最後にfloatが関数になっていて、クラスになってないと思うかもしれませんが、実際そんな感じでしょう。

Pythonのコードで、float型の値を生成するには、
(1) 1.0 とか 1e10 といったリテラルを書く
(2) int, str, bytes といった他の型から変換する
しかありません。
あとはそこから計算していった結果としてしか新たな値(インスタンス)は生成できません。
C言語側にある"float型を生成する真のコンストラクタ"にはPythonからは直接はアクセスできないのです。

ですからfloatの実装のイメージとしては上記のコードで雰囲気は近いはずです。


コメント中で

なぜfloat()をダブルアンスコ付きの関数定義で呼べるのか、という点です。

という表現がでてきますが、逆です。
float()の中ダブルアンスコ付きのメソッド呼んでいます。

上記のように、ビルドインのfloat()の中ダブルアンスコ付きのメソッド呼ぶように実装されているので

python

1>>> class HogeHoge(object): 2... def __float__(self): 3... return 10.0 4... 5>>> x = HogeHoge() 6>>> print(float(x)) # float(x) ⇒ x.__float__() ⇒ HogeHoge.__float__(x) 710.0

みたいに動かせるのです。


__float__()は、一体どこのクラス内に定義されたスペシャルメソッド、スペシャル属性なのでしょうか?

は「float型への変換を考えたいクラス」で定義するメソッドです。が答えです。
組み込み型の範囲で言えば、strやbytesのようなfloatに変換可能なクラスと、数値型のクラスで定義されています。

投稿2021/04/30 06:31

編集2021/04/30 07:03
quickquip

総合スコア11235

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

__bases__は親クラスではありません

親クラスを並べたtupleです。

python

1>>> float.__bases__ 2(object,)

なのでdir(float.__bases__)だとtupleのインスタンスの属性が取れたりします。dir(float.__bases__[0])とかしないと、そもそも無意味です。


また、super()は親クラスではありません。

メソッドの呼び出しを type の親または兄弟クラスに委譲するプロキシオブジェクトを返します。これはクラスの中でオーバーライドされた継承メソッドにアクセスするのに便利です。

組み込み関数 — Python 3.7.10 ドキュメント

python

1class Hoge(float): 2 def f(self): 3 print(super()) 4 print(type(super())) 5 6h = Hoge() 7h.f() 8 9""" => 10<super: <class 'Hoge'>, <Hoge object>> 11<class 'super'> 12"""

super()superクラスのインスタンスを返します。このインスタンスはドット表記で属性アクセスすると親クラスの属性を探索して返してくれますが、それ自体が親クラスの属性を静的に持っている訳ではありません。

あと、print(super())で出てくる文字列は「Hogeクラス、Hogeクラスのインスタンスに対するsuper」であるということを表しているだけで、継承関係は特に表されていません。


dirも正確ではありません。

dir() は主に対話プロンプトでの使用に便利なように提供されているので、厳密性や一貫性を重視して定義された名前のセットというよりも、むしろ興味を引くような名前のセットを返そうとします。また、この関数の細かい動作はリリース間で変わる可能性があります。

組み込み関数 — Python 3.7.10 ドキュメント


メソッドがどこで定義されているのかを確認したい場合、__qualname__属性が実用的でしょう。

python

1class Hoge: 2 def f(self): 3 pass 4 5 def g(self): 6 pass 7 8 9class Fuga(Hoge): 10 def g(self): 11 pass 12 13x = Fuga() 14print(x.f.__qualname__) # => Hoge.f 15print(x.g.__qualname__) # => Fuga.g

python

1>>> float.__float__.__qualname__ 2'float.__float__'

普通にfloatクラス内で定義されています。

投稿2021/04/29 07:11

hayataka2049

総合スコア30935

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sequelanonymous

2021/04/29 07:50 編集

ありがとうございます!調べ方がわるかったのにきづけたのよかったです。 下記のコードで2)の書き方で`__float__`を上書きできるのは理解できます。 しかし、1)の場合は、objectクラスに`__float__`はないはずなのに、なぜ上書きできるのか、というのが本質的には知りたいことでそのためにobjectについて調べていました。 もしご存知でしたらお答えいただけませんでしょうか? ーーーー 1) ```python >>> class Test: def __float__(self): ... ``` 2) ```python >>> class Test(float): def __float__(self): ... ```
hayataka2049

2021/04/29 08:00

元々なければないで、新規に定義されるだけです。 いわゆる「オーバーライド」ではありませんが、それでも勝手に作れます。
sequelanonymous

2021/04/29 08:14

> 元々なければないで、新規に定義されるだけです。 たしかにそうですね。`__float__`で定義するとfloat()関数の挙動がかわる理由は、なぜでしょうか? 組み込まれてるスペシャルメソッドを上書きしたら変更できるという仕様なのはわかっています。具体的にどんな処理の流れで定義されてfloat()とのマッピングをしているのかが気になっています。 > 「オーバーライド」 下記のドキュメントに記載にある`object.`という記述からobjectクラス内にあると仮設をたてたのですが、この`object.`は、いわゆるクラスではなく、何をさしていて、dotでなぜつなげてると思いますでしょうか? [object.__float__(self)](https://docs.python.org/ja/3/reference/datamodel.html#object.__float__)
hayataka2049

2021/04/29 08:14

逆に言うと、「スペシャルメソッドは必ずオーバーライドで定義しなければならない」という縛りはないです。基本的には普通のメソッドと変わらない訳で。
hayataka2049

2021/04/29 08:18

> たしかにそうですね。`__float__`で定義するとfloat()関数の挙動がかわる理由は、なぜでしょうか? float()の挙動は変わりません。 > 一般の Python オブジェクト x に対して、float(x) は x.__float__() に委譲します。 > https://docs.python.org/ja/3.7/library/functions.html#float
hayataka2049

2021/04/29 08:24 編集

floatの__new__は大雑把には以下のようになっていると考えても良いかもしれません(組み込み型なので、当然実際には異なります)。 def __new__(cls, x=None): if x is None: return 0.0 else: return x.__float__()
sequelanonymous

2021/04/29 08:34

> float()の挙動は変わりません。 これは、`class Test`と`class `Test(float)`の両方ともについておっしゃっていますでしょうか? 下記のように挙動を変えてるとおもっていたのですが、なにか理解がまちがっていますでしょうか? ```python >>> class Float: ... def __init__(self, value): ... self.value = value ... def __float__(self): ... return self.value * 2 ... >>> f = Float(3) >>> float(f) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: Float.__float__ returned non-float (type int) >>> f = Float(3.0) >>> float(f) 6.0 ``` > 一般の Python オブジェクト x に対して、float(x) は x.__float__() に委譲します。 ここの箇所、見逃していました。ありがとうございます。
hayataka2049

2021/04/29 08:38 編集

>下記のドキュメントに記載にある`object.`という記述からobjectクラス内にあると仮設をたてたのですが、この`object.`は、いわゆるクラスではなく、何をさしていて、dotでなぜつなげてると思いますでしょうか? 任意のクラスないしインスタンス(書き分けがいまいちですが)だと思えば良いのではないでしょうか。 それか、いっそ片仮名だと思って読む。「オブジェクト.__float__」とか。
hayataka2049

2021/04/29 08:49 編集

floatの挙動は変わらない、の意味は、floatそのものは常に__float__を呼んでその結果を返すということです。当然中で呼ばれる__float__はカスタマイズされ得るのですが、それはfloatの知ったことではないのです。 (当然型チェックなどは行われ、エラーになったら途中で止まったりする訳ですが) (ちなみにここ、新し目のバージョンのドキュメントだと、 > For a general Python object x, float(x) delegates to x.__float__(). If __float__() is not defined then it falls back to __index__(). > https://docs.python.org/ja/3.9/library/functions.html#float という記述になっていますが。とりあえずさっきは邦訳があった3.7を引いています。__float__が未定義の場合、__index__を試すらしい。) 入門サイト的なところだと「float()は型変換する関数です」と書いてあったりしますが、嘘です。float()自身に型変換の機能はありません。あるのは引数に受け取ったオブジェクトに予め実装されている、floatに型変換するメソッドを呼び出す機能だけです。……と書けば伝わるでしょうか。
actorbug

2021/04/29 08:47

横から失礼します。 > 下記のように挙動を変えてるとおもっていたのですが、なにか理解がまちがっていますでしょうか? それは__float__()からfloat型以外を返しているからエラーになっているだけでしょう。 https://docs.python.org/ja/3/reference/datamodel.html#object.__float__ > 組み込み関数の complex(), int(), float() の実装から呼び出されます。 適切な型の値を返さなければなりません。
sequelanonymous

2021/04/29 09:00 編集

To hayataka2049さん > float()の挙動は変わらない、の意味は、常に__float__を呼んでその結果を返すということです。 はい、それはわかっています。 なので上記のコードは、`def __float__(self):`を定義しているのでfloat()の挙動は変わっていると思いますが、認識あっていますでしょうか? そこで、一番知りたいことにつながるんですが、どういう仕組みでfloatを継承せずに`__float__`とかくだけでfloat()の挙動をかえられるのか、です。ご存知でしょうか? つまり、下記のコードです。新規で`__float__`を定義して、なぜfloat()の動きを変更できてるのか、です。 ``````python >>> class Float: ... def __init__(self, value): ... self.value = value ... def __float__(self): ... return self.value * 2 ... >>> f = Float(3) >>> float(f) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: Float.__float__ returned non-float (type int) >>> f = Float(3.0) >>> float(f) 6.0 ```
sequelanonymous

2021/04/29 08:54

> 入門サイト的なところだと「float()は型変換する関数です」と書いてあったりしますが、嘘です。float()自身に型変換の機能はありません。あるのは引数に受け取ったオブジェクトに予め実装されている、floatに型変換するメソッドを呼び出す機能だけです。……と書けば伝わるでしょうか。 はい、それも理解しています。float()って関数でなくてclassなので。
hayataka2049

2021/04/29 09:02

float(x)という呼び出しは内部的にx.__float__()という呼び出しを(可能なら)実行してその結果を(問題がなければ)返すため、 任意のクラス(floatクラスを継承する必要はない)に__float__メソッドを(適切に)実装すれば、float(その任意のクラスのインスタンス)という呼び出しが可能になる。 という説明で良いでしょうか?
sequelanonymous

2021/04/29 09:16 編集

はい、わたしもそこまでは、理解しています。気になっているのは、もっと深い処理についてです。 > 任意のクラス(floatクラスを継承する必要はない)に__float__メソッドを(適切に)実装すれば、float(その任意のクラスのインスタンス)という呼び出しが可能になる。 なぜ、これが可能なのか、どういう順番で呼び出されているのか、です。 float()は、builtin scopeの組み込み型関数で、厳密にはpythonインタプリタに組み込まれてるfloatクラス内のスペシャルメソッドです。そのため、.pyモジュールがよみこまれるときにlocal scope -> enclose -> global -> buitlinって順番にコードがよまれるのですが、そのときにダブルアンダースコアがついてる関数は、builtin scopeより前の段階で定義されてるはずで、定義が上書きされたダブルアンダースコアの関数の定義は、builtin関数とのマッピングをするようにpythonインタプリタ内に実装されているのではないかな、と思った次第です。憶測ですが。
hayataka2049

2021/04/29 09:30 編集

>float()は、builtin scopeの組み込み型関数で、厳密にはpythonインタプリタに組み込まれてるfloatクラス内のスペシャルメソッドです。そのため、.pyモジュールがよみこまれるときにlocal scope -> enclose -> global -> buitlinって順番にコードがよまれるのですが、そのときにダブルアンダースコアがついてる関数は、builtin scopeより前の段階で定義されてるはずで、定義が上書きされたダブルアンダースコアの関数の定義は、builtin関数とのマッピングをするようにpythonインタプリタ内に実装されているのではないかな、と思った次第です。憶測ですが。 特にそういう事実はありません。ぜんぶ間違っています。
sequelanonymous

2021/04/29 09:45 編集

どこの部分がどう間違っていますでしょうか?全部間違っているとして、下記のはどう理解されていますでしょうか? > 任意のクラス(floatクラスを継承する必要はない)に__float__メソッドを(適切に)実装すれば、float(その任意のクラスのインスタンス)という呼び出しが可能になる。 なぜ、これが可能なのか、どういう順番で呼び出されているのか、です。
ppaul

2021/04/29 09:44

hayataka2049さんが書かれているように全部間違っています。 .pyモジュールがよみこまれるときにlocal scope -> enclose -> global -> buitlinって順番にコードがよまれる ではなく、変数の束縛を探すときにlocal scope -> enclose -> global -> buitlinで探すというのが正しい動きです。 ダブルアンダースコアの関数の定義は、builtin関数とのマッピングをするようにpythonインタプリタ内に実装されているのではないか そういうことはありません。 インタプリタが読み込むのはpythonバイトコードです。 dis.disを使って、float()の入ったコードを逆アセンブルして読めばすぐにわかることです。 インタプリタの動きをちゃんと理解したければ、ソースをダウンロードしてPython-3.9.*/Python/ceval.cの3500行目あたりにある case TARGET(CALL_FUNCTION_EX): { のあとを追いかけてみてください。
hayataka2049

2021/04/29 09:47

> float()は、builtin scopeの組み込み型関数で、 関数ではない。クラス。 > 厳密にはpythonインタプリタに組み込まれてるfloatクラス内のスペシャルメソッドです。 float()は厳密にはfloatクラス内のスペシャルメソッドではない。 > そのため、.pyモジュールがよみこまれるときにlocal scope -> enclose -> global -> buitlinって順番にコードがよまれるのですが、 これはスコープの優先順位なのでコードが読まれる順番とは関係ない。むしろ大雑把に言えばこの逆順に読み込まれるとすら考えられる(正確な順番はドキュメントのどっかにあったと思います)。 > そのときにダブルアンダースコアがついてる関数は、builtin scopeより前の段階で定義されてるはずで、 ということはない。Pythonは関数定義だろうが動的なので、コードが実行される順番で定義される。 > 定義が上書きされたダブルアンダースコアの関数の定義は、builtin関数とのマッピングをするようにpythonインタプリタ内に実装されているのではないかな そんな高尚なことは起きていません。
hayataka2049

2021/04/29 09:52

> > 任意のクラス(floatクラスを継承する必要はない)に__float__メソッドを(適切に)実装すれば、float(その任意のクラスのインスタンス)という呼び出しが可能になる。 > なぜ、これが可能なのか、どういう順番で呼び出されているのか、です。 とりあえず、 任意のクラス(floatクラスを継承する必要はない)に__float__メソッドを(適切に)実装すれば、その任意のクラスのインスタンス.__float__()という呼び出しが可能になる。 は良いですよね。 で、floatクラスの__new__が大雑把にどういうものなのかは、上の方にコメントしたので、 それを合わせて考えてみると良いと思います。 それすらわからなければ、floatをクラスだと考えるのを一旦やめて(本当はクラスなのですが単純化して)、 def float(x): return x.__float__() だと思えば良いです。 これ以上の複雑な仕組みは、ない訳なのですが……。
sequelanonymous

2021/04/29 10:06 編集

ありがとうございます! 恐らくわたしの聞き方の問題なきがしていますが、知りたきことは、 floatクラスを継承せずとも、`__float__`メソッドを(適切に)実装するだけでなぜ、呼び出せるのか、という点です。
hayataka2049

2021/04/29 10:11

質問者さんが躓いている点が正直よく理解できていません。 この件について、今の時点で理解できていることと疑問点を整理して、改めて質問を立てていただけませんか?
actorbug

2021/04/29 10:31

逆になぜ呼び出せないと思うのかを問いたい。 def myfloat(x): return x.__float__() みたいな関数を自前で定義すれば呼び出せるのは理解できているのか。 前に上がった__new__の定義を組み込んだクラスを自前で定義すれば呼び出せるのは理解できているのか。 myfloatや自作クラスとfloatとで何が違うから呼び出せないと考えたのか。 組み込みのfloatからユーザ定義の__float__が参照できないと考えたのか 組み込みのfloat内でユーザ定義の関数を実行することはできないと考えたのか
bsdfan

2021/04/29 11:14

静的な型の言語のイメージで考えられているのではないですか? pythonはダックタイピングな言語だから、それで動きますという説明ではダメですか。
quickquip

2021/04/29 15:34

実装するとなぜ呼び出せるのか? というのはさすがに誰にも意図が伝わらない疑問だと思いますよ。 (実装したメソッドは呼び出せて当たり前でしょう)
sequelanonymous

2021/04/29 16:22

ありがとうございます。 疑問は下記に関連しています。 >組み込みのfloatからユーザ定義の__float__が参照できないと考えたのか 参照できるのは仕様です、スペシャルメソッドだからです。までは、理解していて、なぜfloat()をダブルアンスコ付きの関数定義で呼べるのか、という点です。 これが、def float():という書き方で実装してるから呼べます、というのならそれはそうですね、というふうに理解はできます。
hayataka2049

2021/04/30 06:46 編集

このスライドで(__float__は直接登場しませんが)雰囲気を掴むとか。 https://www.slideshare.net/shimizukawa/how-does-python-get-the-length-with-the-len-function どうしても実装が気になるなら、組み込み型のCコードを追えば良いです。この辺りの仕様は私もあまり理解していないので、解説できませんが……。 https://github.com/python/cpython/blob/master/Objects/clinic/floatobject.c.h#L205 https://github.com/python/cpython/blob/master/Objects/floatobject.c#L1616 https://github.com/python/cpython/blob/master/Objects/abstract.c#L1562 参考:https://docs.python.org/ja/3/c-api/typeobj.html ほとんどの開発者はPython/C APIまで理解する必要はないと思われます。
sequelanonymous

2021/04/30 07:14

ありがとうございます!まさに共有頂いたスライドの中身のようなことがしりたかったことでした。
guest

0

super()はTest2の親クラスを返す関数ではなく、クラスsuperのインスタンスを返すコンストラクタです。
t2.__float__は、クラスTest2がfloatから継承した__float__をwrapしたインスタンスメソッドです。
その元になるTest2.__float__は、がfloatから継承しているのでfloat.__float__と同じものです。

python

1>>> class Test2(float): 2... def base_class(self): 3... print(type(super())) 4... print(type(super()) == super) 5... 6>>> t2 = Test2() 7>>> t2.base_class() 8<class 'super'> 9True 10>>> dir(super) 11['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__self__', '__self_class__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__thisclass__'] 12>>> super(Test2, Test2()) 13<super: <class 'Test2'>, <Test2 object>> 14>>> 15>>> Test2.__float__ == float.__float__

を見ると、大体の状況はわかるのではないでしょうか。

組み込み型のfloatは、クラスなので下記のようにbuiltin scope内で定義されているだろうという仮説がたちますが、実際には、どうやらそういった実装にはなっていないようにみえます。

この質問の意味がわかりません。なぜそう思ったのですか?

このobjectは、何者なんでしょうか

class objectは読まれていますね。そこに書いてある通りのものです。

投稿2021/04/29 07:03

ppaul

総合スコア24670

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hayataka2049

2021/04/29 07:18

super()はコンストラクタではないのでは? 式としては「クラスの呼び出し(とは普通言わないと思いますが)」、式を評価した結果としてはインスタンスでしょう。コンストラクタは__init__です。
ppaul

2021/04/29 07:29

私も他の言語出身なのでpythonのインスタンス生成の呼び出しをコンストラクタと呼ぶのは違和感があったのですが、公式ドキュメントの書き方を見ていると、それのことをコンストラクタと書いてあるので、郷に入っては郷に従え、の方針でコンストラクタと書くことにしています。
sequelanonymous

2021/04/29 07:55

> この質問の意味がわかりません。なぜそう思ったのですか? 下記のコードで1)の場合、2)と同じように継承したクラス内の`__float__`をオーバーライドしているならば、1)の場合もobjectクラスを継承しており、objectクラス内にあるであろう`__float__`をオーバーライドしてると思ったからです。 しかし、当質問内のコードにあるようにobjectクラスには、`__float__`はないようなので、なぜ、できるのか、objectクラスとはなにものなのか?という質問の意図になります。 ーーーー 1) ```python >>> class Test: def __float__(self): ... ``` 2) ```python >>> class Test(float): def __float__(self): ... ```
hayataka2049

2021/04/29 08:02

>ppaulさん 今ざっと見たら、確かにそうなってますね……。逆に普通に想像されるコンストラクタって用語としては定義されてないのか。 個人の感想ですが、「コンストラクタ(一般名詞)」として読むべきかな、とは思いました(汗)。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問