Pythonのabc(抽象基底クラス)の価値は何でしょうか?
他の言語で言うところのインターフェースに近い役割だと思っているのですが、そもそもPythonは動的型付け言語なので、あまり意味を成さないように思います。
型ヒントやmypy等を併用する場合は意味があるかと思うのですが、それらと組み合わせて使用することを前提としている機能なのでしょうか?
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答3件
0
ベストアンサー
このモジュールは Python に PEP 3119 で概要が示された 抽象基底クラス (ABC) を定義する基盤を提供します。なぜこれが Python に付け加えられたかについてはその PEP を参照してください。
abc --- 抽象基底クラス — Python 3.9.4 ドキュメント
ということなので、PEP 3119を確認。
This is a proposal to add Abstract Base Class (ABC) support to Python 3000. It proposes:
・ A way to overload isinstance() and issubclass().
・ A new module abc which serves as an "ABC support framework". It defines a metaclass for use with ABCs and a decorator that can be used to define abstract methods.
・ Specific ABCs for containers and iterators, to be added to the collections module.
PEP 3119 -- Introducing Abstract Base Classes | Python.org
筆頭に挙げられているのがisinstance
とissubclass
のオーバーロード、です。二つめはどういう機能か、ということを書いているのであって、普通の内容。三つ目はコンテナやイテレータに特化したABCを用意しますよ、という話です。
ここから読み取れる想定されていたニーズとしては、たとえば、
「引数で受け取ったオブジェクトがSequenceであればちゃんと処理できるという仕様で関数を作る」
ということをやりたいときに、
- 受け取ったオブジェクトがSequenceでないときは適切に例外処理をしたい
- 引数で受け取ったオブジェクトがSequenceかどうかを判定するのは難しい
組み込み型であれば最悪列挙できるかもしれないが……てこと
- だから
isinstance(x, Sequence)
とか書けるとものすごく便利なのではないか
みたいなことだった訳で、つまり「動的に適切な型チェックをする」という方向性だったと考えられます。
我々のように「普通に」Pythonを道具として使うというスタンスでコードを書いているとあまり意識しませんが、高名なライブラリのコードを読むと、外から受け取ったものはだいたいisinstance
の嵐をくぐって、型によってぜんぜん違う処理に分岐したりもし、万が一(?)これは想定されていない型だな……となったときには例外送出して止める、みたいに書いてあります。なので、こういう機能は、要るときは要ります。
型ヒントやmypy等を併用する場合は意味があるかと思うのですが、それらと組み合わせて使用することを前提としている機能なのでしょうか?
に関しては、abc
自体はバージョン 2.6から追加されてしまっており、型ヒントの機能が追加されるのにはるかに先行している、という事実を書き添えておきます。
「アヒルのように見えて、アヒルのように鳴けば、それはアヒルである。」
「鳴き声を聴き比べるコードは共通化した方が良いのではないか。」
うがった見方をした場合……
Pythonは歴史的にはDuck Typingバンザイな文化であったのは確かであり、この場合、たとえばライブラリ製作者の立場で考えると「ユーザが独自定義したいい加減なクラスのオブジェクトが投げつけられてしまう」、逆にライブラリユーザの立場から考えると「どの程度まで独自定義クラスを作り込めばこのライブラリに投げれるのかわからん」という苦悩がそれぞれに発生します。
その辺を統制する仕組みがあると、基本的にはみんな助かったと考えられます。ライブラリ製作者はABCを書けばいいし、ユーザはABCに従って実装すれば良いのですから。
投稿2021/04/08 09:53
編集2021/04/08 10:24総合スコア30935
0
使う側からするとabcのメリットは「mixinでメソッドが追加されることが期待できる」という感じかと思います。
https://docs.python.org/ja/3/library/collections.abc.html
から、例えばABCのSet
を継承して__contains__
, __iter__
, __len__
の3つを実装したら__le__
, __lt__
, __eq__
, __ne__
, __gt__
, __ge__
, __and__
, __or__
, __sub__
, __xor__
, isdisjoint
が全部手に入ることが期待できます。
python
1>>> from collections.abc import Set 2 3>>> class OneToFiveSet(Set): 4... def __contains__(self, x): 5... return isinstance(x, int) and 1 <= x <= 5 6... def __iter__(self): 7... return iter(range(1, 6)) 8... def __len__(self): 9... return 5 10 11>>> s = OneToFiveSet() 12 13>>> s > {1,2,3} # 実装してない__gt__が使える 14True
ただしmixinには抽象クラス(と多重継承)があれば実際は十分です。
Pythonの言語仕様設計者がabcを必要とした理由はまたちょっと複雑そうです。
あるオブジェクトがあるプロトコルを満たしているかは、「あるメソッドを持っているか(=Duck Typing)」だけでは十分じゃないケースがある。精確にはPythonの仕様の中にもう存在してしまっていた。
という理由な気がします。
Sequenceプロトコルがそうです。
Sequenceであるためには、Iterableであってかつ__len__
メソッドを実装している必要があります。が、逆は言えません。つまりIterableであってかつ__len__
メソッドを実装していてもSequenceであるとは限りません。
https://docs.python.org/ja/3/glossary.html#term-sequence
dict は
__getitem__()
と__len__()
もサポートしますが、検索の際に整数ではなく任意の immutable なキーを使うため、シーケンスではなくマッピング (mapping) とみなされているので注意してください。
とあります。
dictがSequenceでないことは表現するには、Duck Typingでは不足です。
それでもdictはSequenceでないということを表現したかったのでしょう。
ここでabcを導入する必要があったのではないでしょうか。
python
1>>> from collections.abc import Sequence 2 3>>> issubclass(dict, Sequence) 4False
実際dictはSequenceではないです。
(追記)
型ヒントやmypy等を併用する場合は意味があるかと思うのですが、それらと組み合わせて使用することを前提としている機能なのでしょうか?
そうだと思いました、という回答でした。
型チェックでdictはSequenceでないことにしたい、つまり
python
1def foo(seq: Sequence): pass 2 3d = {'a': 1} 4foo(d) # ☆
に対して☆で警告をだしたいという要求があります。
それにはDuck Typingでは不足で、そこで導入されたのabcだったのでは、ということです。
投稿2021/04/08 02:43
編集2023/05/05 07:19総合スコア11235
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
pythonのオブジェクト指向に慣れた人にとってはあまり使い道はないと思います。
pythonの公式マニュアルには(「アヒルのように見えて、アヒルのように鳴けば、それはアヒルである。」)インターフェースというのが書かれていて、処理系はこのインタフェースの考え方で作られていますし、多くのユーザはこれをつかっているからです。
他のプログラミング言語のオブジェクト指向に慣れた人はABCを使いたいかもしれません。
クラスの階層を気にするひとにとっては、スーパークラスを定義してからサブクラスを定義するというトップダウンな定義をしなくても、後付けでスーパークラスを定義できるからです。
投稿2021/04/07 22:00
総合スコア24670
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/04/11 03:25