Python クラスの定義 - class
Publish date: 2021-03-05
Last updated: 2022-02-11
Last updated: 2022-02-11
Pythonでクラス(class)を定義する方法です。
クラスの定義
Pythonのクラスはキーワードclass
を使って定義できる。
特別なメソッド__init__
でインスタンス生成時の処理を定義できる。
class SampleClass:
"""クラスのサンプル"""
def __init__(self, name):
"""コンストラクタ"""
self.name = name
def say(self):
"""サンプルのメソッド"""
print(self.name)
インスタンスの生成はクラス名()
で行う。
sc = SampleClass("taro")
sc.say() # => taro
クラス変数とインスタンス変数
クラス直下に記述した変数はクラスに属するスタティックな変数のようにアクセスできる。 self以下に定義した変数はインスタンス変数となる。
class SampleClass:
static_list = [10, 20 , 30]
def __init__(self):
self.instance_list = []
def add(self, item):
self.instance_list.append(item)
sc1 = SampleClass()
sc2 = SampleClass()
sc1.add(1)
sc2.add(2)
sc1.static_list.append(40)
sc2.static_list.append(50)
# インスタンス変数は、インスタンス毎に値が保持される
sc1.instance_list # => [1]
sc2.instance_list # => [2]
# スタティック変数(クラス変数)は、クラスで共通する値として保持する
sc1.static_list # => [10, 20, 30, 40, 50]
sc2.static_list # => [10, 20, 30, 40, 50]
# クラス名.名称でアクセスできる
SampleClass.static_list # => [10, 20, 30, 40, 50]
ただし、同名のインスタンス変数を定義すると、 クラス変数が見えなくなってしまう。
sc1.static_list = ['a']
sc1.static_list # => ['a']
sc2.static_list # => [10, 20, 30, 40, 50]
プロパティ
プロパティは組み込みの関数property
を使って定義できる。
class SampleClass:
def __init__(self):
self._name = None
def get_name(self):
return self._name
def set_name(self, value):
self._name = value
def del_name(self):
del self._name
name = property(get_name, set_name, del_name, "name property")
sc = SampleClass()
sc.name = 'Taro'
print(sc.name) # => Taro
デコレータ@property
で読取専用のプロパティを定義することも可能。
class SampleClass:
def __init__(self, name):
self._name = name
@property
def name(self):
return self._name
sc = SampleClass('Taro')
print(sc.name) # => Taro
デコレータsetter
,deleter
を使うと、値の設定と削除を行えるプロパティを定義できる。
class SampleClass:
def __init__(self):
self._name = None
@property
def name(self):
return self._name
@name.setter
def name(self, value):
self._name = value
@name.deleter
def name(self):
del self._name
sc = SampleClass()
sc.name = 'Taro'
print(sc.name) # => Taro
del sc.name
print(sc.name) # => AttributeError: 'SampleClass' object has no attribute '_name'
継承
継承はクラス名の後に丸括弧で継承元のクラスを指定する事で行える。
class Animal:
def __init__(self, weight):
self.weight = weight
def w(self):
print(self.__class__.__name__, self.weight)
class Dog(Animal):
pass
class Cat(Animal):
pass
d = Dog(123)
c = Cat(77)
d.w() # => Dog 123
c.w() # => Cat 77
継承したクラスの初期化
class SampleClassBase:
def __init__(self, name=""):
self.name = name
class SampleClass(SampleClassBase):
def __init__(self, name="", age=0):
super().__init__(name)
self.age = age
プライベート変数
Pythonでは、priavate
といったキーワードで変数やメソッドを隠蔽する方法はない。
慣習的に、アンダースコアで始まるメソッドや変数は非公開として扱い、 特にアンダースコアを2つ重ねると自動で変数が難号化(mangle)されて公開される。
class SamplePriavate:
def __init__(self, name):
self.__name = name
def say(self):
print(self.__name)
sp = SamplePriavate("taro")
print(sp._SamplePriavate__name) # => "taro"
# print(sc.__name) # => AttributeError: 'SampleClass' object has no attribute '__name'
名称の置き換えは名前マングリング(name mangling)と言われ、_クラス名__変数名
に置換される。
スタティックメソッド(static method)、クラスメソッド(class method)
インスタンスレベルでのメソッドではなく、クラスにメソッドを定義したい場合がある。
Pythonでは、メソッドにデコレータ@classmethod
や@staticmethod
をつけることで実現できる。
@classmethod
の場合、引数としてクラスcls
が渡ってくるので継承する可能性がある場合はこちらが使える。
class StaticClassSampleBase:
def instance_method(self, n):
print(n)
@classmethod
def class_method(cls, n):
print(cls, n)
@staticmethod
def static_method(n):
print(n)
class StaticClassSample(StaticClassSampleBase):
pass
scs = StaticClassSample()
scs.instance_method(1) # => 1
scs.class_method(2) # => <class '__main__.StaticClassSample'> 2
StaticClassSample.class_method(3) # => <class '__main__.StaticClassSample'> 3
scs.static_method(4) # => 4
StaticClassSample.static_method(5) # => 5