pythonは使うけどclassとかよくわからん。
でもpytorchにclassが頻出なので勉強する必要がある。
同じような立場の人が心理障壁を下げるために使っていただけたらと思う。
正しい理解は公式ドキュメント9:classを参照してください。
#とりあえず関数「def」
処理したい操作に名前と引数を指定することができる。
def kakezan(a, b):
return a*b
kakezan(9, 9)
81
実行結果は次のようにして変数に保存できる。
times99 = kakezan(9, 9)
#classについて一番かんたんな構造で考える
ただの情報の値の入った箱と考える
class keisan:
num1=1
num2=2
クラスの中の情報をドット記号を使って取り出すことができる。
keisan.num1
引数とイコールで結ぶと、情報の入った箱を移し替えるようなイメージで扱える
box1 = keisan()
box1
<__main__.keisan at 0x7f5e03896b38>
クラスの名前が出力される
box1.num1
中身をドットで取り出すことができる。
#box1というオブジェクトの変数を書き換える
box1.num1=10
box1.num1
10
#コンストラクタ
オブジェクトが生成される時に必ず実行されるメソッド(class内の関数)のこと
class keisan:
num1=1
num2=2
def __init__(self):
print('必ず表示される')
box3 = keisan()
classを変数に入れるとコンストラクタ部分が実行される
必ず表示される
上記のselfは必ず書くおまじないである
selfがさしている対象は上記であればbox3
今は処理が何もないが、必ずなにか引数を入れなさい。という指示にも使える
class keisan:
num1=1
num2=2
def __init__(self,name1,age1):
print('一人目の名前は' + name1 +
'で年齢は' + str(age1) + 'です。これは毎回表示されます。')
box4 = keisan()
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-7-df434c06b06e> in <module>()
7 'で年齢は' + str(age1) + 'です。これは毎回表示されます。')
8
----> 9 box4 = keisan()
TypeError: __init__() missing 2 required positional arguments: 'name1' and 'age1'
なにも入れないとprintが実行できないからエラーになる。
box4 = keisan(name1='Mike',age1=19)
一人目の名前はMikeで年齢は19です。これは毎回表示されます。
表示処理しておわり。
このままでは入力したものが取り出せない。
box4.name1
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-9-53236fb457a0> in <module>()
----> 1 box4.name1
AttributeError: 'keisan' object has no attribute 'name1'
エラーになる
保存したければ引数をつくっておく
class keisan:
num1=1
num2=2
def __init__(self,name1,age1):
self.name1=name1
self.age1=age1
print('一人目の名前は'+name1+'で年齢は'+str(age1)+'です。これは毎回表示されます。')
box5 = keisan('Rachel',22)
box5.name1
Rachel
とりだせた。
#引数は無いけど決まった処理を行いたい時
class keisan:
num1=1
num2=2
def __init__(self,val1):
self.val1=val1
def plus10(self):
self.val1 +=10
box6 = keisan(val1=15)
box6.val1
15
クラス内のplus10メソッドを使う
box6.plus10()
box6.val1
25
#クラス内のオブジェクトを変更するメソッド
引数はselfでなくclsにする
class keisan:
num2=2
def __init__(self,val1):
self.val1=val1
def plus10(self):
self.val1 +=10
def plus5(cls):
cls.num2 +=5
box7 = keisan(val1=22)
box7.num2
2
classのnum2を変更するメソッドのplus5を実行する
box7.plus5()
box7.num2
7
クラス内のnum2が変更できた
#お作法 変えてほしくない
classを設計して他人にコードを公開する時、設計上変更してほしくない部分は「_」記号を付ける。
class keisan:
def __init__(self,val1,val2):
self._val1=val1 #変えてほしくない
self.val2=val2 #変えてもいい
box9 = keisan(10,20)
print(box9._val1)
print(box9.val2)
10
20
box9._val1 = 30
box9._val1
30
変えられちゃうんですけどね
#もうちょっと変えてほしくない気持ちを強くする
class keisan:
def __init__(self,val1,val2):
self.__val1=val1 #変えてほしくない気持ちを強く
self.val2=val2 #変えてもいい
box10 = keisan(10,20)
box10.__val1
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-15-68ebfca72338> in <module>()
6
7 box10 = keisan(10,20)
----> 8 box10.__val1
AttributeError: 'keisan' object has no attribute '__val1'
エラーになる
確認できなくなった。
#どうしても触りたいときは「_クラス名」を間に挟む
クラス名の確認
print(type(box10))
<class '__main__.keisan'>
クラス名はkeisanと確認できる
box10._keisan__val1
10
確認できた。
_が一つよりも隠せた。
#名前空間がよくわからないけど
名前空間とは名前からオブジェクトへの対応付けに関係する概念
モジュール1番(機能のまとまり。関数のまとまりをイメージ)の中にある関数1がある。
おなじ名前の関数は、別のモジュールの中で定義されていたらなば、同じ名前でも別物として扱える
このような関数は異なった名前空間の関数の名前であり、関係は持たない
らしいので確かめる
class cs1:
def __init__(self,val1):
self.val1=val1
def cal1(self,val2):
self.kekka = self.val1 * val2
class cs2:
def __init__(self,val1):
self.val1=val1
def cal1(self,val2):
self.kekka = self.val1 + val2
class1 = cs1(10)
class1.cal1(15)
print(class1.kekka)
class2 = cs2(10)
class2.cal1(15)
print(class2.kekka)
150
25
同じ関数の名前でも別のclassのメソッドであれば別処理が行われる。
#追記
以下コメントにて
クラス内の値を変更することで、クラスを割り当てた先の値が共有されてしまう問題
>>> class keisan:
... value = 123
...
>>> box1 = keisan()
>>> box2 = keisan()
>>> keisan.value
123
>>> box1.value
123
>>> box2.value
123
>>> keisan.value = 456
>>> keisan.value
456
>>> box1.value
456
>>> box2.value
456
に対して、取れる方法としては
それぞれが固有に持つ値として振っておくこと
class new_keisan:
def __init__(self):
self.value = 123
new_box1 = new_keisan()
new_box1.value
>>123
new_keisan.value = 456
new_keisan.value
>>456
new_box1.value
>>123
new_box2=new_keisan()
new_box2.value
>>123