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

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

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

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

Q&A

解決済

3回答

2274閲覧

Pythonのabc(抽象基底クラス)の価値は何でしょうか?

raise_a_hand

総合スコア26

Python

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

1グッド

1クリップ

投稿2021/04/07 20:20

Pythonのabc(抽象基底クラス)の価値は何でしょうか?
他の言語で言うところのインターフェースに近い役割だと思っているのですが、そもそもPythonは動的型付け言語なので、あまり意味を成さないように思います。

型ヒントやmypy等を併用する場合は意味があるかと思うのですが、それらと組み合わせて使用することを前提としている機能なのでしょうか?

yuji38kwmt👍を押しています

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

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

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

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

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

guest

回答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

筆頭に挙げられているのがisinstanceissubclassのオーバーロード、です。二つめはどういう機能か、ということを書いているのであって、普通の内容。三つ目はコンテナやイテレータに特化した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
hayataka2049

総合スコア30933

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

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

raise_a_hand

2021/04/11 03:25

ありがとうございます。 > たとえばライブラリ製作者の立場で考えると「ユーザが独自定義したいい加減なクラスのオブジェクトが投げつけられてしまう」、逆にライブラリユーザの立場から考えると「どの程度まで独自定義クラスを作り込めばこのライブラリに投げれるのかわからん」という苦悩がそれぞれに発生します。 ここの点は重要かと思いました。 実際、あるABCを継承し、必要なabstractメソッドを実装しないと、そのクラスを初期化した時点でエラーが発生する認識です。 これは他の言語におけるインターフェースと同じ仕組みかと思います。 この仕組みによって、ライブラリ製作者は開発者にインターフェースに沿って実装することを強要できますし、開発者も何を実装したら良いか明確なので楽ですね。 社内で共通基盤を作る際なども便利そうです。
guest

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
quickquip

総合スコア11055

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

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

0

pythonのオブジェクト指向に慣れた人にとってはあまり使い道はないと思います。

pythonの公式マニュアルには(「アヒルのように見えて、アヒルのように鳴けば、それはアヒルである。」)インターフェースというのが書かれていて、処理系はこのインタフェースの考え方で作られていますし、多くのユーザはこれをつかっているからです。

他のプログラミング言語のオブジェクト指向に慣れた人はABCを使いたいかもしれません。

クラスの階層を気にするひとにとっては、スーパークラスを定義してからサブクラスを定義するというトップダウンな定義をしなくても、後付けでスーパークラスを定義できるからです。

投稿2021/04/07 22:00

ppaul

総合スコア24666

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.46%

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

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

質問する

関連した質問