Pythonオブジェクト指向

クラスの作成

class クラス名:
	def メソッド名(self,引数,,):
class Member:
    def setName(self,n):
        self.name = n

    def showName(self):
        print(self.name)

クラスからインスタンス(オブジェクト)を生成

クラスはインスタンスを生成しないと使えない。

# Memberクラスのオブジェクト生成
m = Member() 

m.setName("田中")
m.showName()

上の例のmはMemberインスタンスを入れるための変数。Member()でMemberクラスのインスタンスを生成している。

コンストラクタ

class Member:
    def __init__(self):
        self.name = "鈴木"

    def showName(self):
        print(self.name)

インスタンス生成の例(上のMemberクラスの場合)

m = Member()
m.showName() # 鈴木と表示

インスタンス生成時に引数を付ける

class Member:
    def __init__(self,name):
        self.name = name

    def showName(self):
        print(self.name)

m = Member("田中")
m.showName() # 田中と表示

特殊メソッド

__init__のように特殊なメソッドをクラス内に作ることが出来る。

文字列化

__str__ というメソッドを作るとstr関数を行ったときに自動的に呼ばれる。

class Member:
    def __init__(self):
        self.name = "鈴木"

    def __str__(self):
        return self.name + "さん"

m = Member()
print(str(m)) # 鈴木さんと表示

このような型変換を行うメソッドでは他に __int__ や __float__ などがある。

長さ(len)

__len__ というメソッドを作るとlen関数を行ったときに自動的に呼ばれる。

class Member:
    def __init__(self):
        self.name = "鈴木"

    def __len__(self):
        return len(self.name)

m = Member()
print(len(m)) # 2と表示

配列

__getitem__ というメソッドを作るとインスタンス[添え字]を行ったときに自動的に呼ばれる。

class Member:
    def __init__(self):
        self.name = "鈴木"

    def __getitem__(self, n):
        return self.name[n]

m = Member()
print(m[0]) # 鈴と表示

代入用に__setitem__ もある

class Member:
    def __init__(self):
        self.name = "鈴木"

    def __setitem__(self, n, value):
        self.name = self.name[:n] + value + self.name[n+1:]

m = Member()
m[0] = '山'
print(m.name) # 山木と表示

private

Pythonでは基本的にメンバはpublicであり、外部から全てアクセスできる。しかし、擬似的にprivateを実現することも出来る。それは属性名の先頭に__(アンダーバー2個)を付けること

class Member:
    def __init__(self,name):
        self.__name = name

m = Member('鈴木')
print(m.__name) # エラー

※ただし、m._Member__name ではアクセスできてしまうのであくまで擬似的。

このとき @poperty デコレーションを付けたメソッドを作ると属性のようにアクセス可能(読み取り専用)。

class Member:
    def __init__(self,name):
        self.__name = name
        
    @property
    def name(self):
        return self.__name

m = Member('鈴木')
print(m.name)

@属性名.setter デコレーションで属性の設定も可能。

class Member:
    def __init__(self,name):
        self.__name = name
        
    @property
    def name(self):
        return self.__name
    
    @name.setter
    def name(self, value):
        self.__name = value

m = Member('鈴木')
m.name = "山田"
print(m.name)

継承

スーパークラス(親クラス)の属性・メソッドを全て引き継いでサブクラスを作る

class サブクラス名(スーパークラス名):
class Animal:
    def __init__(self,name):
        self.name = name

    def showName(self):
        print(self.name)

class Dog(Animal):
    def naku(self):
        print("ワン")

d = Dog("ポチ")
d.naku() # ワンと表示
d.showName() # ポチと表示

super().メソッド名 でスーパークラス(親クラス)のメソッドを呼び出せる。

class サブクラス名(スーパークラス名):

class Animal:
    def __init__(self,name):
        self.name = name

    def showName(self):
        print(self.name)

class Dog(Animal):
    def __init__(self,name,type):
    	super().__init__(name);
    	self.type = type
    	
    def naku(self):
        print("ワン")

    def showName(self):
        print(self.type)
        super().showName();

d = Dog("ポチ","芝犬")
d.showName() # 柴犬 ポチと表示

データクラス

3.7以降。データを入れるためのクラスを明示的に定義。コンストラクタは自動生成される。基本的な使い方はクラスと同じ

from dataclasses import dataclass

@dataclass
class User:
    name: str
    age: int = 0
    
    def show(self):
        print(f'{self.name}さん。{self.age}歳')

u = User('田中',30) 
u.show()

print(u.name) # 田中
print(u.age) # 30
# コンストラクタの直後に何かする場合 __post_init__ 関数を定義
class User:
    name: str
    age: int = 0
    namelen: int = 0

    def __post_init__(self):
        self.namelen = len(self.name)

# 変更不能にする
@dataclass(frozen=True)
class User:
    name: str
    age: int = 0
# 辞書に変換
d = dataclasses.asdict(u)
print(d)