疑問
- Pythonにおける一般的なクラスとdataclassをどのように使い分けるのか?
1-1. 一般的なクラスで実装することを選択する(dataclassに対する)メリットは何か?
2. クラスではなく、トップレベルで関数を定義するのはどのようなときか?
3. ユーティリティクラスやインスタンスの変数を参照しないメソッドを作ることについてどのように考えるか?
3-1. Pythonでは一般的なのか?
現在の考え
- 基本的に
dataclass
で実装する - また、基本的に
frozen=True
で実装することで極力イミュータブルにする - トップレベルの関数を作ることにやや抵抗がある(Javaなど他の言語が原因?
- 「関数とユーティリティクラスは禁止 - 株式会社アークシステム(infoARK)」を読んでなるべく、作らないようにしてきた。しかし、上同様、Pythonでは話が変わってくるのではないかと思うようになった
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答4件
0
1について
dataclass
は一種の糖衣構文的な機能なので、これまでの通常のクラス定義でも書いていたor書こうと思っていたものを自動生成してくれるだけです。
dataclasses --- データクラス — Python 3.7.4 ドキュメント
python 3.7以前で稼働させないのであれば、ゴリゴリ使っても誰も怒らないと思います。
immutableにするかどうかは、慎重に考えた上でimmutableのメリットが活かせるかどうかで決めないといけません。なんでもimmutable的な発想には反対します。
2について
あえてオブジェクトにしなくていいようなときはすべてトップレベル関数、という方針もありえます。疎結合の関数でうまく書ければ。
個人的には、クラスを自分で書くときはちょっと覚悟を固めます。だからなんだという話ですが。そんなにしょっちゅうはクラスをいじりたくない、ということです。
3について
Javaなどではそうするしかない面もありますが、pythonの場合はモジュールが気楽に作れてその中にトップレベル関数も作れるので、それでいいと思います。
非クラスベース的な設計も受け入れる懐の深い言語なので、非クラスベース的な設計で書けばいいのです。それでもちゃんと書けばオブジェクト指向プログラミングとして成立するということもあります。
(Pythonを使う限り、すべてがオブジェクトなので)
投稿2019/08/03 06:53
総合スコア30933
0
ベストアンサー
1 について
「必要な時に使えば良い」という雰囲気かなと思います。
GitHub に転がっているライブラリを見るとそのへんの雰囲気も掴めるのではないでしょうか。
◯ 機能
dataclasses の主な機能は、よく使うメソッドを変数アノテーションを元に自動的に生成してくれることだと思っています。PEP の Abstract に書いてあります。
◯ 背景
dataclasses と、似たようなライブラリはいくつもあったのに、なぜわざわざ dataclasses を作ったのか? PEP には以下のように書かれています。
One main design goal of Data Classes is to support static type checkers.
Rationale < PEP 557 - Data Classes
FastAPI
しかし、FastAPI という型アノテーションを使っているウェブフレームワークも dataclasses は、特に使っていません。
使わないのに @dataclasses
がついていると、どこかで使うのかな?と考えてしまいますね笑
2 について
複数のクラスで使う関数なら使ってもいいかなと思います。
◯ 筆者の意図は...
この記事面白いですね。他も読みました。プライベートメソッドを使うときは他のクラスが隠れているとかも面白かったです。
多人数での大規模な開発を想定する場合、筆者の主張通りトップレベルの関数は確かに書かない方が良い気がします。
たしかに筆者の意図としては「想定されない使われ方をするから」ユーティリティクラスは使うなということだと思います。
例えば自分みたいなテキトーな人間が100人も寄せ集まってトップレベル関数を使っていたら、誰かしら2、3人は想定外な作り方をしそうです、自信があります!笑
クラス定義文を使い名前空間を、きっちり分けて影響範囲を絞っておいた方が安全だと思います。
オブジェクト指向とは個人的に名前空間を分けることだと思っています。
◯ Kotlin について
ただ実際、問題として、どのクラスにも所属しない汎用的な処理を書いた関数は存在します。
わざわざクラスに分けるのは、とても面倒です。そこまで大規模にやらない場合は、厳密に分ける必要もないかなとも思います。
例えば Java は必ずクラスを書かないといけませんが...
java
1// Java 2public class Sample{ 3 public static void main(String args[]){ 4 printSum(3, 4); 5 } 6 public static void printSum(int a, int b){ 7 System.out.println(a + b); 8 } 9}
Java の後継的なポジションにる Kotlin では必ずしもクラスを書く必要がなくなりました。「トップレベルで関数を書けるようになった」ということです。
kotlin
1// Kotlin 2fun main(args: Array<String>) { 3 printSum(3, 4) 4} 5 6fun printSum(a: Int, b: Int) { 7 println(a + b) 8}
「トップレベルで関数を書けるようになった」ということは、絶対に書いてはいけないというわけではないということかなと思います。
3 について
ユーティリティクラスやインスタンスの変数を参照しないメソッドを作ることについてどのように考えるか?
もし複数のクラスで使う「ユーティリティクラス」が存在する場合は、トップレベルで関数を書けばいいと思います。
また、特定のクラスだけで使う「インスタンスの変数を参照しないメソッド」がある場合は staticmethod
を使って定義すればいいと思います。
まとめ
質問の意図としては大規模なものでも耐えうる設計がしたいということだと思うのですが、実際の現場などに行ってみないとわからないのかなと思ったりもします。自分もわかりませんが...
個人で勉強されるうちは dataclasses にしても class にしても YAGUNI の精神で肩の力を抜いて tuple, dict, class の順に使えばいいかなと思います。
投稿2019/08/03 08:04
総合スコア830
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
JavaだからPythonだからなんて違いはないでしょう。
Javaだって議論は同じで、
https://teratail.com/questions/203779#reply-301210
の質問/回答と根は同じです。
- 状態を持たず、同じ呼び出しに同じ値を返すような関数
- オブジェクトを作成する関数
- インスタンスの状態に紐付かない、外部公開しないような補助関数
- 多様なオブジェクトに使えるユーティリティ関数
などはモジュールのトップレベルに定義してもぜんぜん構わないでしょう。
Pythonでは、クラスのstaticmethodやclassmethodよりもモジュールのトップレベル関数を好む傾向が強い(感じがする)ぐらいの違いしかないかと思います。
- についてはhayataka2049さんと同じ感想なので割愛。
投稿2019/08/03 07:26
総合スコア11038
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
面白そうな話題なので思ったことをつらつらと。
まずdataclass
に関しては、まだ慣習と呼べるほど用法用量が定まっていないと感じます。まだ出たてですし。私個人としては、後方互換等を考えるとcollections.namedtuple
のほうを推します。読み取り専用属性が多いクラスも、
python
1class Person(namedtuple("_Person", "name age address")): 2 ...
みたいに書いたりします。
次にトップレベルで関数を定義
に関しては、私個人としては逆に、クラスの定義よりも頻度が高いです。Pythonはマルチパラダイムなので、私は「クラスは必要になるまで定義しない」派です。
最後にユーティリティクラス
とインスタンスの変数を参照しないメソッド
については、私は好きではないです。それよりもユーティリティモジュール
とトップレベルの関数
のほうが好きです。
投稿2019/08/03 12:10
総合スコア6142
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。