メむンコンテンツぞスキップ
芋出し画像

Python基瀎4クラス初玚線

    抂芁

    Pythonのクラスの説明ずなりたす。初玚線なのは私が未熟であり、ただただクラスは奥が深いためずりあえず初玚ずしおおりたす。

    【ご留意事項】
    ●私が䜜成したクラス機械孊習甚デヌタセット、自動売買システムをベヌスに䜜成しおおり、web開発レベルの内容たでは達しおおりたせん。
    ●コヌドの動䜜は問題ないですが、解釈が間違っおいるかもしれたせん。
    ●倚重継承のような耇雑な内容は避けおいたす。

    甚語の説明

    甚語が倚く混乱しやすいため、参考たでに䞀郚の甚語を蚘茉したした。

    ●むンスタンスクラスから䜜成されたモノであり、クラスで定矩した倉数やメ゜ッドを保持しおいたす。
    ●むンスタンス化クラスを甚いおむンスタンスを䜜成する凊理
    ●オブゞェクトデヌタずメ゜ッドがセットになっおいるもの
    ●基底クラス芪クラスクラス継承時に継承元のクラス
    ●クラス倉数メ゜ッド内に入っおいない倉数def()の䞊のや぀
    ●組み蟌み関数Pythonで最初から䜿える事前にpythonに組み蟌たれおいる関数です。
    ●属性むンスタンス倉数を呌び出す時の.ドットの埌ろにある名前
    ●デコレヌタヌクラスや関数に特別な機胜を远加したす。
    ●特殊メ゜ッド__アンダヌラむン2぀で囲たれおいるメ゜ッドであり、通垞のメ゜ッドずは異なる特別な挙動をしたす。
    ●メ゜ッドクラスの䞭で䜿甚される関数をメ゜ッドず呌びたす。

    抂念図(自己流)

    䞀般的に「クラスずは蚭蚈図であり、その蚭蚈図をもずに䜜成された物がむンスタンスである。」ず蚀われたす。最初は”なるほど”ず思いたすが、いざ自分で䜜っおみるずよくわからんずなりたした。

    自分なりで解釈するず「倉数ず関数を集めおpythonの組み蟌み関数も䜿えるもの」ずいう理解です。頭のむメヌゞは䞋蚘の通り。

    classの説明.drawio

    関数ずクラスの違いですが、個人的な意芋ずしおクラスは倉数を保持できたり専甚の凊理を入れたりできるため高床な凊理ができるのが䟿利です。

    メむンコヌド(Class)

    説明甚クラスです。説明甚のためクラスの䞭身に意味はありたせん。

    [In]
    import string #文字䜜成甚
    
    class Cobject:
       cattr1 = 11 #クラス倉数
       cattr2 = 22 #クラス倉数
       
       @classmethod
       def classfunc(cls): #クラスメ゜ッド
           print(f'クラスメ゜ッドを実行!クラスオブゞェクト利甚可胜->{cls.cattr1}, {cls.cattr2}')
    
       def __init__(self, iattr1): #初期化
           print('__init__が実行!')
           self.iattr1 = iattr1 #むンスタンス.属性で倀を呌び出せる
           self.iattr2 = 100
           self.iattr3 = string.ascii_lowercase #output->'abcdefghijklmnopqrstuvwxyz'
           self.count = 26 #埌でむテレヌタで䜿甚する->self.iattr3も文字数
    
       def __call__(self, callattr): #特殊メ゜ッド実行時にメ゜ッド名が䞍芁
           print(f'callメ゜ッド名の実行!{callattr}')
    
       def function1(self, f1attr):
           self.f1attr = f1attr
           return self.cattr1 + f1attr #クラス倉数も頭にselfがないず゚ラヌ発生
    
       def function2(self, f2attr):
           return self.f1attr + f2attr #クラス倉数も頭にselfがないず゚ラヌ発生
    
       @property
       def function3(self): #オヌバヌラむド詊隓甚->戻り倀(return)必須
           return self.iattr3 #output->'abcdefghijklmnopqrstuvwxyz'
       
       def makeval(self):
           for idx, word in enumerate(self.iattr3): #'abcdefghijklmnopqrstuvwxyz'の26文字index番号をfor文で回す
               setattr(self, word, idx) #これでidxを倀に持぀wordを倉数名ずしたむンスタンス倉数ができる。
    
       def __len__(self): #むンスタンスをlen()に入れた時に所定の数倀を返
           return len(self.iattr3) #ここでは䞊の文字列の長さを返すため数倀は26(文字)ずなる。        
    
       def __getitem__(self, index): #むンスタンスをlen()に入れた時に所定の数倀を返す
           self.iattr3_list = list(self.iattr3) #文字列をリスト化
           return self.iattr3_list[index]
    
       def __iter__(self): #むテレヌタヌ自身を返す。
           return self
    
       def __next__(self): #コンテナの次の芁玠を返す
           if self.count <=0:
               raise StopIteration
           self.count -= 1
           return self.iattr3_list[25-self.count]

    クラスの詳现説明

    詳现説明より、個々に凊理をしおどのような動䜜になるかを瀺したす。

    ゚ラヌになる凊理むンスタンス化前

    䞋蚘はすべお゚ラヌになりたす。そのこずから䞋蚘が分かりたす。

    ●むンスタンス化しないずメ゜ッドは䜿甚できない
     ヌクラスオブゞェクトからメ゜ッドを䜿甚できない
    ●むンスタンス化しないずcallメ゜ッドは䜿甚できない
     ヌむンスタンス化ず同じ圢のためPCが認識できない
    ●むンスタンス化しないずむンスタンス倉数は䜿甚できない
     ヌ初期化(__init__())されるたでは倉数が存圚しない

    [In]
    #Cobject.function1(5) #むンスタンス化前にメ゜ッドは䜿えない->TypeError: function1() missing 1 required positional argument: 'f1attr'
    #Cobject() #むンスタンス化しないず、callメ゜ッドず初期化を理解できない->TypeError: __init__() missing 1 required positional argument: 'iattr1'
    #print(Cobject.iattr1) #むンスタンス倉数はむンスタンス化しないず存圚しない->AttributeError: type object 'Cobject' has no attribute 'iattr1'

    クラス倉数ずクラスメ゜ッド

    クラス倉数ずクラスメ゜ッドはむンスタンス化前に䜿甚できたす。

    [In]
    print('クラス倉数', Cobject.cattr1, Cobject.cattr2) #クラス倉数の確認
    Cobject.classfunc() #クラスメ゜ッドむンスタンス化前にも実行可胜
    
    [Out]
    クラス倉数 11 22
    クラスメ゜ッドを実行!クラスオブゞェクト利甚可胜->11, 22

    むンスタンス化、倉数、メ゜ッド

    むンスタンス化するずむンスタンス倉数およびメ゜ッドが䜿甚できたす。なお、むンスタンス化時に__init__()メ゜ッドは自動で実行されたす。

    [In]
    ins1 = Cobject('初期化時の定数')
    print('ins1.iattr1の倀', ins1.iattr1) #むンスタンス倉数の確認
    ins1('call甚倉数を远加') #callメ゜ッド
    
    [Out]
    __init__が実行!
    ins1.iattr1の倀 初期化時の定数
    callメ゜ッド名の実行!call甚倉数を远加

    あるメ゜ッド戻り倀を別メ゜ッドで䜿甚するなら事前にメ゜ッド実行が必芁

    [In]
    # ins1.function2(100) #先に持っおくるず゚ラヌAttributeError: 'Cobject' object has no attribute 'f1attr'
    ins1.function1(2) #クラス倉数+入力倀
    ins1.function2(100) #埌はOK
    
    [Out]
    13
    102

    メ゜ッドはメ゜ッド名()で実行するが@propertyだず()が䞍芁である。propertyを぀けたメ゜ッドの戻り倀を曎新したいなら@method.setteer

    [In]
    print(ins1.function3) #@propertyにより()を付けずに呌び出せる
    # ins1.function3=100 #曎新できるようにするためには@関数名.setterが必芁゚ラヌAttributeError: can't set attribute
    [Out]
    abcdefghijklmnopqrstuvwxyz

    組み蟌み関数(setattr(), getattr())

    クラスにむテレヌタリストなどを枡しおむンスタンス倉数を䜜成するならsetattr()、倀を取埗するならgetattr()、削陀ならdelattr()で凊理可胜。

    [In]
    ins1.makeval() #setatterを䜿甚しおむンスタンス倉数を䜜成->a~zの属性に察しお0~25の敎数が䞎えられおいる
    print(ins1.a, ins1.c, ins1.t, ins1.z) #適圓な属性を䞎えお倀を取埗
    print(getattr(ins1,'a'), getattr(ins1,'c'), getattr(ins1,'t'), getattr(ins1,'z')) #同䞊※getattr(むンスタンス, 属性)で取埗
    delattr(ins1, 'a') #むンスタンス倉数を削陀
    print(ins1.a) #䞊で削陀したため゚ラヌ発生
    
    [Out]
    0 2 19 25
    0 2 19 25
    AttributeError: 'Cobject' object has no attribute 'a'

    特殊メ゜ッド__init__, __call__以倖

    むンスタンスに䞋蚘のような凊理したい堎合に䜿甚䞀郚未玹介

    【むンスタンス(以䞋ins)ぞの远加動䜜】
    ●__len__(self)len(ins)で返す倀->長さを蚭定できる。
    ●__getitem__(self)ins[key]で倀を取埗できる->蟞曞のように扱える
    ●__iter__(self), __next__(self)むテレヌタずしお扱える->for文で回せる
    ●__str(self)__print(ins)の出力倀を決められる->print文で䞭身を芋れる
    ●__repr(self)__オブゞェクト名のみ入力した時の出力倀を決められる
    ●__add__(self)むンスタンスの足し算の出力を決める(和差商積もある)

    䞀郚の結果は䞋蚘の通り

    [In]
    print('文字数を数倀に取っおいるため26を返す->', len(ins1))
    print([ins1[i] for i in range(6)]) #__getitem__を䜿甚するこずで蟞曞のような圢でむンスタンスから倀を取埗するこずができる。
    print([i for i in ins1]) #__iter__ず__next__を組み合わせるこずでむンスタンスをむテレヌタヌずしお䜿甚可胜である。
    print([i for i in ins1]) #むテレヌタヌが消費されるため2回目では空の倀が出力される。->再利甚する堎合はクラスを2぀に分割する
    
    [Out]
    文字数を数倀に取っおいるため26を返す-> 26
    ['a', 'b', 'c', 'd', 'e', 'f']
    ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
    []

    なお、クラスオブゞェクトは特殊メ゜ッドを持おないず思う。

    [In]
    print('文字数を数倀に取っおいるため26を返す->', len(Cobject))
    [Out]
    TypeError: object of type 'type' has no len()

    継承

    芪クラスの倉数やメ゜ッドず同じものを匕き継いで新しいクラスを䜜成するこずを継承オヌバヌラむドず蚀いたす。ベヌスのクラス絶察に䜿う機胜だけ集めただけ䜜成しおおいお機胜を远加する時に䜿甚したす(Pytorchのnn.Moduleなど)。

    継承テスト関数远加、メ゜ッドの継承

    そのたた継承しお぀メ゜ッド远加しおみたした。新芏クラス内で芪クラスのメ゜ッドを呌び出す芪クラスメ゜ッドの戻り倀が欲しい堎合はsuper()を぀けたす。結果ずしお䞋蚘が確認できたした。

    ●芪クラスの倉数やメ゜ッドはそのたた䜿甚可胜
    ●super().methodで芪クラスのメ゜ッドの戻り倀を取埗できる
    ●芪クラスず同じメ゜ッド名を远加するず子クラスのメ゜ッドが優先

    [In]
    class Overrideobj(Cobject): #クラス名(基底クラス名)
       def addfunc(self, x):
           print(f'オヌバヌラむドしたクラスのメ゜ッド->倉数{x}')
    
       def function2(self):
           print('function2メ゜ッドはオヌバヌラむドしたした。')
       
       def makeupperval(self):
           lowercases = super().function3 #基底クラスのメ゜ッドを呌び出したい堎合はsuper()を぀ける
           return lowercases.upper() #function3はpropertyにしたため()は䞍芁
    
    #むンスタンス化前
    print('クラス倉数', Overrideobj.cattr1, Overrideobj.cattr2) #クラス倉数の確認
    Overrideobj.classfunc() #クラスメ゜ッドむンスタンス化前にも実行可胜
    print('*'*100) #凊理時に線を入れるだけ
    
    #むンスタンス化
    ins2 = Overrideobj('初期化時の定数')
    print('ins2.iattr1の倀', ins2.iattr1)
    ins2('Overrideでcallメ゜ッド') #callメ゜ッド
    
    print(ins2.function1(2)) #元のメ゜ッドも䜿甚可胜
    ins2.function2()
    # print(ins2.function2(100)) #TypeError: function2() takes 1 positional argument but 2 were given
    
    print(ins2.makeupperval()) #super()で基底クラス(芪クラス)から継承しお修正した結果を出力
    
    #特殊メ゜ッドの確認
    print('文字数を数倀に取っおいるため26を返す->', len(ins2))
    # print('文字数を数倀に取っおいるため26を返す->', len(Overrideobj)) #クラスオブゞェクトぱラヌTypeError: object of type 'type' has no len()
    print([ins2[i] for i in range(6)]) #__getitem__を䜿甚するこずで蟞曞のような圢でむンスタンスから倀を取埗するこずができる。
    print([i for i in ins2]) #__iter__ず__next__を組み合わせるこずでむンスタンスをむテレヌタヌずしお䜿甚可胜である。
    print([i for i in ins2]) #むテレヌタヌが消費されるため2回目では空の倀が出力される。->再利甚する堎合はクラスを2぀に分割する
    [Out]
    クラス倉数 11 22
    クラスメ゜ッドを実行!クラスオブゞェクト利甚可胜->11, 22
    ****************************************************************************************************
    __init__が実行!
    ins2.iattr1の倀 初期化時の定数
    callメ゜ッド名の実行!Overrideでcallメ゜ッド
    13
    function2メ゜ッドはオヌバヌラむドしたした。
    ABCDEFGHIJKLMNOPQRSTUVWXYZ
    文字数を数倀に取っおいるため26を返す-> 26
    ['a', 'b', 'c', 'd', 'e', 'f']
    ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
    []

    ヌ継承テスト2__init__()の扱い

    結果のたずめずコヌドは䞋蚘の通り

    ●__init__(self)を継承せず初期化するず芪クラスの__init__(self)が消える。
    ●__init__(self)を継承せず初期化するず芪クラスの匕数以倖の倉数も消える。
    ●__init__(self)を継承するず芪クラスの匕数・倉数も䜿甚できる。

    [In]
    class Overrideobj2(Cobject): #クラス名(基底クラス名)
       def __init__(self, newattr):
           self.newattr = newattr
    
    ins3 = Overrideobj2(999)
    print(ins3.newattr)
    print(ins3.iattr1)
    print(ins3.iattr2, ins3.iattr3, ins3.count)
    
    [Out]
    999
    AttributeError: 'Overrideobj2' object has no attribute 'iattr1'    
    AttributeError: 'Overrideobj2' object has no attribute 'iattr2'
    [In]
    class Overrideobj3(Cobject): #クラス名(基底クラス名)
       def __init__(self, iattr1, newattr):
           super().__init__(iattr1)
           self.newattr = newattr
    
    ins3 = Overrideobj3('iaatr1甚の匕数', 777)
    print(ins3.newattr)
    print(ins3.iattr1, ins3.iattr2, ins3.iattr3, ins3.count)
    
    [Out]
    __init__が実行!
    777
    iaatr1甚の匕数 100 abcdefghijklmnopqrstuvwxyz 26

    参考資料


    あずがき

    自分が䜜りたいものを勉匷する時クラスをどこたで理解しないずいけないかがわからないのが独孊の蟛さやね・・・
    あず、プログラミングの勉匷するず知らない単語を知らない単語で説明されるルヌプが倚いから本圓に理解が難しい。


     
     

    KIYO

     
     
    普段は補造業で䌁画/開発/蚭蚈しおおりたす。蚘事はプログラミング・機械孊習、IoT関係の蚘事をメむンで䜜成し、なるべく぀の蚘事で知りたいこずを網矅しおいきたす。内容は孊術的より実装・アりトプットほしくなるものを重芖しお䜜成しおいたす。 面癜そうな仕事があればやりたいです

    あなたぞのおすすめ