元の回答
質問1
何故 data の方は 初期化しないか理解できません。
何故ここでは name のみを初期化しているのでしょうか。
質問のコードの引用元:
(159) Python超入門コース 合併版|Pythonの超基本的な部分をたった1時間で学べます【プログラミング初心者向け入門講座】 - YouTube
ざっと見た感じ特に理由は述べられていなかったので
製作者のみ知るところですが、
予想としては、これは「超入門コース
」であるためと思われます
入門者に教えるためには、難しいことを覆い隠して
順序立てて教える必要があります
いきなり難しいことを教えても、基礎がなければ理解することができないこともあるからです
ここでは設計が洗練されていることを犠牲にしてでも
引数を与えることができることを教える意図
があったのではないかと思われます
設計としては data
もアトリビュートとして持たせる設計の方が良いかもしれません
質問2
みなさんは自分でクラスを作成する際、
どういった判断基準で、初期化する/しないを分けているのでしょうか。
状態
を持つ必要があるかどうかで判断します
初期化というか、アトリビュートを定義するということは、状態
を持つということです
今回の例では、生徒に点数を状態
として持たせると、
次のように、クラスを呼び出している側のコードの変数を減らせます:
python
1class Student:
2
3 def __init__(self, name, data):
4 self.name = name
5 self.data = data
6
7 def calculate_avg(self):
8 sum = 0
9
10 # data の 中身である[70,65,50,90,30]を num で左から格納する
11 for num in self.data:
12 sum += num
13
14 avg =sum/len(self.data)
15 return avg
16
17 def judge(self):
18 if(self.calculate_avg() >= 60):
19 result = "passed"
20 else:
21 result = "failed"
22 return result
23
24a001 = Student("sato", [70,65,50,90,30])
25
26print(a001.calculate_avg())
27print(a001.name)
28print(a001.judge())
実行結果:
console
1$ python test.py
261.0
3sato
4passed
リンク先の例のプログラムでは、
処理が 1 回で終わっているのでさほど不便を感じなかったかもしれませんが、
少なくとも、変数が散らかっています:
python
1a001 = Student("sato")
2data = [70,65,50,90,30]
3avg = a001.calculate_avg(data)
4judge_result = a001.judge(avg)
5
6print(avg)
7print(a001.name)
8print(judge_result)
もし、クラスが状態
を持ってくれていれば、次のようにスッキリします:
python
1a001 = Student("sato", [70,65,50,90,30])
2
3print(a001.calculate_avg())
4print(a001.name)
5print(a001.judge())
これは、クラスが点数を状態
としてを持ったので、
クラスの外で変数として状態
を持つ必要がなくなったためです
追記
アトリビュート定義(状態を持たせる)のと、初期化せず、外で変数を持たせるかどうかは、
実装する機能の仕様に合わせて、
ソースコードがより簡潔に短くなる方をアトリビュートとして採用すべき、ということでしょうか。
回答者によって見解が分かれるかもしれませんが、個人的には、ほぼ、その認識でよいと思います
設計としてはアトリビュートを定義する方が正しい場合でも、
ごくまれにですが、余計にコードが煩雑になる場合もあります
そのような場合はソースコードが簡潔に短くなる方の設計を採用することもあります
「インスタンスごとに、アトリビュートを定義する必要がある」
との説明があったのですが、今回の場合、
name と data のいずれかをアトリビュートとして定義しないと、
そもそもインスタンス化ができない、という理解であってますでしょうか。
コンストラクターの定義によります
今回のコードはコンストラクター内でアトリビュートを定義しています
しかし、そのコンストラクターに、アトリビュートの値として使われる引数を渡さなかった場合、
コンストラクターの呼び出しでエラーが発生します
例えば次のような場合はインスタンス化できずエラーとなります:
python
1class Student:
2
3 def __init__(self, name):
4 self.name = name
5
6a001 = Student()
7print(a001.name)
実行結果:
console
1$ python test.py
2Traceback (most recent call last):
3 File "test.py", line 6, in <module>
4 a001 = Student()
5TypeError: __init__() missing 1 required positional argument: 'name'
次のように、コンストラクターの引数に初期値を定義しておくと、エラーは発生しません:
python
1class Student:
2
3 def __init__(self, name="Taro"):
4 self.name = name
5
6a001 = Student()
7print(a001.name)
実行結果:
console
1python test.py
2Taro