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

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

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

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

Q&A

解決済

2回答

1724閲覧

Pythonのクラスについて

bbbjoker1218

総合スコア8

Python

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

0グッド

0クリップ

投稿2019/10/28 10:18

編集2019/10/28 10:48

現在、pythonを勉強していますがとあるサイトリンク内容で以下のコードを見つけたのですが
return cls(friend_name, origin.school, *args)と
mitsu = WorkingStudent.friend(hiro, "Mitsu", 15.00)のコードが一体何をしているのかわかりません。
ご教授お願い致します。

※コードとコメントは引用です。

Python3

1class Student: 2 def __init__(self, name, school): 3 self.name = name 4 self.school = school 5 self.marks = [] 6 7 def average(self): 8 """平均成績を返す 9 10 インスタンス変数にアクセスしたいのでinstancemethodを使う。 11 """ 12 return sum(self.marks) / len(self.marks) 13 14 @classmethod 15 def friend(cls, origin, friend_name, *args): 16 """同じ学校の友達を追加する。 17 18 継承クラスで動作が変わるべき(継承クラスでは salaryプロパティがある) 19 なのでclassmethodを使う。 20 子クラスの初期化引数は *argsで受けるのがいい 21 """ 22 return cls(friend_name, origin.school, *args) 23 24 @staticmethod 25 def say_hello(): 26 """先生に挨拶する 27 28 継承しても同じ動きでいいのでstaticmethodを使う 29 """ 30 print("Hello Teacher!") 31 32class WorkingStudent(Student): 33 def __init__(self, name, school, salary): 34 super().__init__(name, school) 35 self.salary = salary 36 37hiro = WorkingStudent("Hiro", "Stanford", 20.00) 38mitsu = WorkingStudent.friend(hiro, "Mitsu", 15.00) 39print(mitsu.salary)

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

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

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

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

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

bbbjoker1218

2019/10/28 10:48

ご指摘ありがとうございます。 コードの引用元のURLを追加しました。
meg_

2019/10/28 11:05

デバッグしてコードの動きを追ってみるのが良いと思います。
guest

回答2

0

ベストアンサー

まずはクラスクラスメソッド継承についてさらっと記載します。

クラス

Python言語ではクラス構文を利用して、クラスに変数や関数を定義できます。

クラスと呼ばれるテンプレートの様なものから、インスタンスと呼ばれる値を埋め込んだものを作成できます。

py

1class Person: 2 # __init__はPerson()としたときに必ず呼ばれる関数 3 # 変数nameを設定している 4 def __init__(self, name): 5 self.name = name 6 7 def get_name(self): 8 return self.name 9 10my = Person('yamada') 11 12print(my.get_name()) # クラスに関数が設定されている 13print(my.name) # クラスに変数が設定されている

クラスメソッド

先ほどクラスはテンプレートの様なもの、と記載しました。
クラスメソッドでは引数にクラスそのものが入るので、クラス自身を指します。

py

1class Person: 2 name = 'tanaka' # クラス変数 3 4 def __init__(self, name): 5 self.name = name # メンバ変数 6 7 @classmethod 8 def get_name_from_class(cls): 9 return cls.name 10 11 def get_name_from_member(self): 12 return self.name 13 14print(Person('yamada').get_name_from_class()) 15print(Person('yamada').get_name_from_member())

get_name_from_class関数はクラスメソッドなので、cls引数にはPersonクラスが入ります。
それに対してget_name_from_memberはクラスメソッドではないので、self引数にはPerson('yamada')インスタンスが入ります。

継承について

また親クラスを子クラスが継承することが出来ます。

py

1class Person: 2 def __init__(self, name): 3 self.name = name 4 5 def get_name(self): 6 return self.name 7 8 9class Child(Person): # class 子クラス名(親クラス名)で継承できる 10 def __init__(self,name, age): 11 super().__init__(name) # superメソッドで親クラスを参照できる 12 self.age = age 13 14 def get_age(self): 15 return self.age 16 17my = Child('yamada', 12) 18 19print(my.get_name()) # 親クラスの変数、関数を利用できる 20print(my.get_age()) # 子クラスの機能も利用できる

上記を踏まえた上で説明します。

WorkingStudent("Hiro", "Stanford", 20.00)WorkingStudentクラスが初期化されます。

WorkingStudentは親クラスStudentを継承しているので、friend関数が使えます。

そしてfriend関数はStudentのクラスのクラスメソッドです。
またクラスメソッドは呼び出したクラスに属します。

第一引数であるcls変数にはWorkingStudentクラス自身が入ります。
第二引数であるoriginにはhiroインスタンスが入ります。

そしてfriend_name"Mitsu"*args15.00が入ります。

なのでreturn cls(friend_name, origin.school, *args)で実質WorkingStudent("Mitsu", hiro.school, 15.00)となるわけです。

投稿2019/10/28 11:25

編集2019/10/28 11:52
nobodytolove123

総合スコア61

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

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

bbbjoker1218

2019/10/28 11:44

丁寧な解説ありがとうございます。 理解できました。
nobodytolove123

2019/10/28 11:50

お役に立てれば幸いです。 一部嘘をついてしまったので、修正させて下さい...。
bbbjoker1218

2019/10/28 12:32

どの部分が間違いだったのでしょうか?
nobodytolove123

2019/10/28 13:01

失礼しました。 クラスインスタンスは継承されたのクラスに属すと記載しましたが、正しくは呼び出されたクラスに属す。です。
bbbjoker1218

2019/10/28 13:07

訂正ありがとうございました。 ちなみに、クラスメソッドとスタティックメソッドはどのように使い分けたらいいのでしょうか?
nobodytolove123

2019/10/28 13:23

僕も詳しくないのでただの意見になってしまいますが、クラスメソッドは引数に自分自身を取れるので、自身を利用した新しいインスタンスを作る場合に使う時とかですかね。 スタティックメソッドの方が、かなり汎用的に使われていると思います。 主観ですが、静的な機能を実装する場合、スタティックメソッドの方が汎用的に使い回されている気がします。 リンクの方も参考にしてください。 https://blog.pyq.jp/entry/Python_kaiketsu_190205 https://www.st-hakky-blog.com/entry/2017/11/15/155523?amp=1
bbbjoker1218

2019/10/28 14:07

ありがとうございます。 いろいろ調べたのですがこれといった解説がされているサイトがなかったので質問させていただきました。 リンクを参考にいろいろコードを書いてみます。
guest

0

python

1 @classmethod 2 def friend(cls, origin, friend_name, *args): 3 """同じ学校の友達を追加する。 4 5 継承クラスで動作が変わるべき(継承クラスでは salaryプロパティがある) 6 なのでclassmethodを使う。 7 子クラスの初期化引数は *argsで受けるのがいい 8 """ 9 return cls(friend_name, origin.school, *args)

このクラスメソッドが第一引数で受け取ったクラスをインスタンス化して返しています。第一引数には、メソッドが属するクラスが自動的にバインドされます。

python

1mitsu = WorkingStudent.friend(hiro, "Mitsu", 15.00)

シンプルに上述のクラスメソッドを呼び出しています。

投稿2019/10/28 11:16

hayataka2049

総合スコア30933

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

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

bbbjoker1218

2019/10/28 11:45

わかり易い解説ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問