パソコン仕事5倍塾
35,000人を指導した東大卒・元日本IBM社内講師が直伝
MENU
藤本 博子さんの投稿
(投稿ID: 5419)
print(silver.get_asset_type())
print(f'Metal.get_asset_typeは、{Metal.get_asset_type()}') #地金 print(f'silver.asset_typeは、{silver.asset_type}') #silver print(f'silver.get_asset_type()は、{silver.get_asset_type()}') #地金
Metal.get_asset_typeは、地金 silver.asset_typeは、silver silver.get_asset_type()は、地金
小川 慶一さんのコメント
(コメントID: 7955)
class AttrSample: # クラス変数 att_class_instance = 100 def __init__(self): # インスタンス変数 self.att_instance = 200 @classmethod def func_class_method(cls): # クラスメソッド print('func_class_method') def func_instance_method(self): # インスタンスメソッド print('func_instance_method') attr_sample = AttrSample() # インスタンスは、クラス属性にもインスタンス属性にもアクセスできる # クラス変数/クラスメソッド(OK) print(attr_sample.att_class_instance) AttrSample.func_class_method() # インスタンス変数/インスタンスメソッド(OK) print(attr_sample.att_instance) attr_sample.func_instance_method() # クラスは、クラス属性にアクセスできるが、インスタンス属性にはアクセスできない # クラス変数/クラスメソッド(OK) print(AttrSample.att_class_instance) AttrSample.func_class_method() # インスタンス変数/インスタンスメソッド (NG 以下の2行どちらもエラーになります) # print(AttrSample.att_instance()) # AttrSample.func_instance_method()
class AttrSample: my_attr = 100 def __init__(self): self.my_attr = 200 attr_sample = AttrSample() # インスタンスがインスタンス属性と同名のクラス属性にアクセスするには、.__class__ を使う print(attr_sample.__class__.my_attr) #100
class AttrSample: my_attr = 100 def __init__(self): self.my_attr = 200 def my_method(self): # [a] return 'インスタンスメソッドとして定義された my_method' @classmethod def my_method(cls): # [b] return 'クラスメソッドとして定義された my_method' attr_sample = AttrSample() print(attr_sample.__class__.my_attr) print(attr_sample.__class__.my_method()) # [b] が呼ばれる
藤本 博子さんのコメント
(コメントID: 7958)
(コメントID: 7959)
@classmethod def my_method(self): #[b] print(f'self.__name__は、{self.__name__}') return 'クラスメソッドとして定義されたmy_method'
100 self.__name__は、AttSample クラスメソッドとして定義されたmy_method
@classmethod def my_method(cls): #[b] print(f'cls.__name__は、{cls.__name__}') return 'クラスメソッドとして定義されたmy_method'
100 cls.__name__は、AttSample クラスメソッドとして定義されたmy_method
(コメントID: 7960)
(コメントID: 7963)
class Metal: allowed_types = ['silver', 'gold', 'platinum', ] def __init__(self, type_name, total_price, amount): if type_name not in self.allowed_types: raise ValueError(f'許可されてないタイプです:{type_name}')
(コメントID: 7964)
class Asset: asset_type = "資産" def __init__(self, total_price, amount, ): self.total_price = total_price self.amount = amount if __name__ == '__main__': jp_bond = Asset(10000, 1000) jp_bond.asset_type = '日本国債' # [1] instance_asset_type = jp_bond.asset_type class_asset_type = Asset.asset_type instance_class_asset_type = jp_bond.__class__.asset_type print(instance_asset_type) print(class_asset_type) print(instance_class_asset_type) print(id(instance_asset_type)) print(id(class_asset_type)) print(id(instance_class_asset_type))
日本国債 資産 資産 2303352879600 2303352879504 2303352879504
class Asset: asset_type = "資産" def __init__(self, total_price, amount, ): self.total_price = total_price self.amount = amount if __name__ == '__main__': jp_bond = Asset(10000, 1000) # jp_bond.asset_type = '日本国債' # [1] instance_asset_type = jp_bond.asset_type class_asset_type = Asset.asset_type instance_class_asset_type = jp_bond.__class__.asset_type print(instance_asset_type) print(class_asset_type) print(instance_class_asset_type) print(id(instance_asset_type)) print(id(class_asset_type)) print(id(instance_class_asset_type))
資産 資産 資産 2425636370832 2425636370832 2425636370832
(コメントID: 7965)
Captcha:
たった1ヶ月で人生が劇的に変わりました
佐藤信さん
役員クラスの方から高い評価を受けるようになりました。
佐賀県 - 岩本徹さん
今までまったく知らなかったショートカットキーを使いまくっています。
東京都 - 鷹觜慶さん
年齢60才間近、営業で外回りの時間が多い私でも退社時間が1-2時間程度早くなりました。
東京都 - 宗内隆明さん
受講前もすでにパソコン得意でしたが、そんな私でも受講して本当に良かったと思えた講座です。
東京都 - 佐伯とも子さん
ここまで包括的に仕事に役立つ深い学びを受けれた講座は初めてでした
東京都 - 飯田倫子さん
2024年12月24日 07:22
2024年12月23日 21:50
2024年12月23日 10:10
2024年12月15日 22:47
2024年12月14日 06:16
2024年12月24日 20:37
2024年12月24日 11:02
2024年12月24日 10:40
2022年02月24日 10:59
表示できる投稿はありません。
この学習サイトの教材制作、サポート、システム開発をすべてやっています。
2022年02月02日 00:00
2022年02月02日 03:00
2022年02月02日 06:00
2022年02月02日 09:00
2022年02月02日 12:00
2024年12月19日 11:30
2024年12月18日 13:30
2024年10月21日 17:30
2024年10月18日 17:00
2024年10月17日 17:30
2024年11月27日 11:48
2024年11月25日 12:07
2024年11月17日 09:51
2024年11月15日 16:41
2024年11月15日 13:07
藤本 博子さんの投稿
(投稿ID: 5419)
お手数をおかけしますが、どうぞよろしくお願いいたします。
※クラスとインスタンスのread.mdのサンプルコードP9とサンプルコード「part09_43_class_method.py」21行目にかかれた、インスタンス変数でクラスメソッドを実行しているコードについて
生成したインスタンス「silver」を@classmethod def get_asset_type(cls):を実行するメソッドがかかれています。
・クラスメソッドはクラスをインスタンス化せずに実行するメソッド
動画でも、class Metalでメソッドを実行するデモでした。
しかし、サンプルコードとread.mdには上記のメソッドが書かれてました。
・インスタンス変数(silver)を生成したときは、コンストラクタで属性を初期化するか、
インスタンスメソッドを使用すると理解してました。
(1)__init__メソッドのコンストラクタでasset_typeを引数type_nameの値で設定する
(2)もしくは、インスタンスメソッド(第一引数self)で設定
インスタンス変数に対して、クラスメソッドを実行することがあるのかな…と思ったため、ご教示いただけると、ありがたいです。
・Metal.set_asset_type('地金')の式を実行しても、インスタンス変数でsilverのasset_typeの属性を"silver"で設定した値が維持される。
・インスタンス変数silverでクラスメソッドを実行すると、クラスメソッドで設定した属性が設定される。
お手数をおかけしますが、どうぞよろしくお願いいたします。
小川 慶一さんのコメント
(コメントID: 7955)
さすが、鋭い...ですね (^^;
まず、大原則を示します。
なお、以下で、「属性」とは、変数/メソッドの両方をひっくるめた言い方です。(念のため)
[1] インスタンスは、インスタンス属性にアクセスできる。
[2] インスタンスは、クラス属性にアクセスできる。
[3] クラスは、クラス属性にアクセスできる。
[4] クラスは、インスタンスにアクセスできない
[2] については、クラス属性と同名のインスタンス属性がある場合、インスタンスは、インスタンス属性のほうにアクセスします。
ここで、「では、クラス属性と同名のインスタンス属性がある場合、インタンスは、どうやってクラス属性にアクセスするのだ?」という問題があります。
これについては、「属性」とひとくくりにせず、以下の2つに分けて解説します。
[2-1] クラス変数と同名のインスタンス変数がある場合
[2-2] クラスメソッドと同名のインスタンスメソッドがある場合
[2-1] については、まず、クラス変数にアクセスするときは、 .__class__ 属性経由でなんとかなります:
[2-2] については、「手練れの技」的なものを駆使すればおもしろい実験もできないことはないのですが...。クラス/インスタンスの挙動にかなり慣れた方でないとソースを読んでも混乱するばかりなので、ここでは説明を省きます。
今回は、「以下のように同名のメソッドを同一クラス内で複数定義するのは無理」ということだけ覚えておいてください。[a] と [b] のどちらが後に書かれているかによって実行結果が変わります。後に定義されたものが残ります。
以下では、後に書かれた [b] が実行されます。
もしも [a] と [b] の位置を入れ替えると、エラーが出るようになります。(エラーになるのは、 [4] で説明したとおり、 [a] はインスタンスメソッドなので、クラスからは呼び出せないからです)
「後に定義されたものが残る」なら、「前に定義さたもの」は、まるまる無駄ですし、コードを読む人を混乱させるだけですね。
ということで、まずは、この説明でいかがでしょうか。
なお、上記 [2-1], [2-2] のような話は、キワキワなケースの件です。
上記のような .__class__ を経由しないとアクセスできないようなものにアクセスする必要があるコードを書かなくてはならないとしたら、そもそも設計を見直したほうがよいです。
実際、僕自身、自分が書いたクラスに対してインスタンスがこういうコードでクラス属性にアクセスするようなコードを書くことはありません。
人が作ったライブラリを利用するコードを書くときに、仕方なくやることがたまにあるくらいですね。
まずは、以上のとおりです。
藤本 博子さんのコメント
(コメントID: 7958)
丁寧に紐解き、解説くだしまして、ありがとうございました。
>「属性」とは、変数/メソッドの両方をひっくるめた言い方です。(念のため)
属性が変わる、と安易な言い方をしておりました。
クラス変数の動画を見直し、先生がクラスのプロパティが変更される際、どのような表現をされているか見直しました。
あと、以下の説明についても、コードと解説いただいたことにより、腑に落ちました。
>もしも [a] と [b] の位置を入れ替えると、エラーが出るようになります。(エラーになるのは、 [4] で説明したとおり、 [a] はインスタンスメソッドなので、クラスからは呼び出せないからです)
>「後に定義されたものが残る」なら、「前に定義さたもの」は、まるまる無駄ですし、コードを読む人を混乱させるだけですね。
今回ご教示いただたいたこと、動画見直ししたことで理解が深まりました。
本当にありがとうございます!!
藤本 博子さんのコメント
(コメントID: 7959)
@classmethod def my_method(self): #[b]の第一引数(self)は、第一引数を(cls)にしても同じ結果になるのですが、今回の事例で分かりやすいようselfにしていただいたのかなぁ、と思いました。
クラスメソッドの動画で、第一引数をclsにしなくてもよいけれども、clsとするのがよい、と教えていただきました。
小川 慶一さんのコメント
(コメントID: 7960)
すいません。これは、僕のうっかりミスです。
元投稿内のコードを修正しておきました。
ご指摘、ありがとうございます m(_ _)m
藤本 博子さんのコメント
(コメントID: 7963)
「インスタンス作成の演習1」 27:00あたり
・クラス変数(list)"allowed_types"を生成
・コンストラクタ呼び出し時に、受け取った引数"type_name"の値が、list"allowd_types"以外の場合は例外の処理をする。というコードがでてきます。
self.allowed_typesと書くことでクラス属性にアクセスしていることを理解しつつつ、学習をすすめることができました。
self.__class__.allowed_typesと書いても動く
[1] インスタンスは、インスタンス属性にアクセスできる。
[2] インスタンスは、クラス属性にアクセスできる。
[3] クラスは、クラス属性にアクセスできる。
[4] クラスは、インスタンスにアクセスできない
ありがとうございました。
ありがとうございました。
小川 慶一さんのコメント
(コメントID: 7964)
こんばんは。
ちょっと気になるので...以下、サンプルコードです。
クラス変数と同名のインスタンス変数を作ることができます。([1])
そのとき、インスタンス変数が新たに生成されますが、この生成されたインスタンス変数はクラス変数に影響を与えません。
[1] がないと asset_type という名前のインスタンス変数はないので、 jp_bond.asset_type でアクセスできるのはクラス変数です。
藤本さんの理解と一致しているでしょうか。
override_asset_type.py
以下は、上記コードを実行したときの出力例。
インスタンス変数とクラス変数でidが異なります。違うものを参照しているからです。
以下では、上記 [1] をコメントアウトしました。
そのとき、 jp_bond.asset_type でアクセスしているのは、クラス変数です。
not_override_asset_type.py
以下は、上記コードを実行したときの出力例。
インスタンス変数とクラス変数でidが異なります。違うものを参照しているからです。
両者での出力結果の違いに違和感なければOKです。
藤本 博子さんのコメント
(コメントID: 7965)
ご返事と事例をもとに解説くださいまして、ありがとうございます。
理解に違和感はございません。
>クラス変数と同名のインスタンス変数を作ることができます。([1])
そのとき、インスタンス変数が新たに生成されますが、この生成されたインスタンス変数はクラス変数に影響を与えません。
クラス変数の動画 08:46あたりで学習しました。
silve.asset_type = '私の貴金属'とインスタンスで同名の"asset_type"という変数を定義して、その値を"私の貴金属"とした場合について
・クラスの方が書き換わったのでなく、インスタンスの方に新しい変数"asset_type"という変数ができて、その値が”私の貴金属”に変わった。
・インスタンスが自分で新しく"asset_type"という名前の変数を作った
・よってクラス変数の値は変わらない
・インスタンス変数の値は変わった
動画10:10のあたりでインスタンスからはアクセスできなくなるのか?
アクセスするには__class__メソッドを使うと、もとのクラスの値をアクセスできる
という説明も学習できました。
演習1のクラス変数でallowed_typesとself.allowed_typesのid関数の戻り値を確認してみました。
結果は同じオブジェクトIDでした。
id関数を使って検証しておりませんでした。
確認する方法について復習、気づきをいただくとこができました。
ありがとうございます。