Help us understand the problem. What is going on with this article?

python使うけどclassはよくわからん、のでチュートリアルする

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のメソッドであれば別処理が行われる。

以上

参考:pythonドキュメント9.クラス

追記

以下コメントにて
クラス内の値を変更することで、クラスを割り当てた先の値が共有されてしまう問題

>>> 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
Ringa_hyj
R,python,ML,社内コンサル。 元:生命科学(創薬有機),製品開発・実験計画 現在:製造業,概念検証(需要予測,異常検知,etc.) https://amazongodman.github.io/
https://sit-jhonny.hatenablog.com/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away