とほほのPython入門 - クラス
- クラス(class)
- クラス変数・インスタンス変数(attribute)
- メソッド(method)
- アクセス制限(_, __)
- コンストラクタ(__init__)
- デストラクタ(__del__)
- 文字列化(__str__)
- 継承(inheritance)
- 親クラス(super())
- 多重継承
- クラス階層
クラス(class)
Python の クラス(class)は次のように定義します。クラス名は慣習的に大文字で始めます。
class MyClass:
"""A simple example class""" # 三重クォートによるコメント
def __init__(self): # コンストラクタ
self.name = ""
def getName(self): # getName()メソッド
return self.name
def setName(self, name): # setName()メソッド
self.name = name
a = MyClass() # クラスのインスタンスを生成
a.setName("Tanaka") # setName()メソッドをコール
print(a.getName()) # getName()メソッドをコール
クラス定義の冒頭には、"""...""" で ドキュメントストリング を記述することができます。
def MyClass:
"""A sample class"""
(略)
クラス変数・インスタンス変数(attribute)
クラスは、インスタンス変数 と クラス変数 を持つことができます。インスタンス変数は「インスタンス.変数名」で表され、インスタンス毎に独立の変数です。コンストラクタ __init__(後述)の中で初期化することをお勧めします。
class MyClass:
def __init__(self):
self.name = "" # インスタンス変数
a1 = MyClass()
a1.name = "Tanaka"
a2 = MyClass()
a2.name = "Suzuki"
print(a1.name) #=> Tanaka
print(a2.name) #=> Suzuki
クラス変数は「クラス名.変数名」で表され、すべてのインスタンスで共通の変数です。
class MyClass:
PI = 3.14 #=> クラス変数
print(MyClass.PI) #=> 3.14
下記は、クラス変数を用いてインスタンスの個数をカウントアップするサンプルです。
class MyClass:
count = 0 # クラス変数を初期化
def __init__(self):
MyClass.count += 1 # クラス変数をカウントアップ
a1 = MyClass()
a2 = MyClass()
print(MyClass.count) #=> 2
クラス変数やインスタンス変数は、動的に追加することができます。
class MyClass:
pass
a1 = MyClass()
a1.name2 = "Tanaka" # インスタンス変数の追加
MyClass.PI2 = 3.141593 # クラス変数の追加
インスタンス変数が存在しない場合、「インスタンス.変数名」はクラス変数を参照することに注意してください。「インスタンス.変数名」に値を代入した時点でインスタンス変数が生成され、以降はインスタンス変数が参照されます。
class MyClass:
PI = 3.14
a1 = MyClass()
a2 = MyClass()
print(a1.PI) # クラス変数 MyClass.PI(3.14) が参照される
a1.PI = 3.141593 # インスタンス変数 a1.PI が生成される
print(a1.PI) # インスタンス変数 a1.PI(3.141593)が参照される
print(a2.PI) # クラス変数 MyClass.PI(3.14) が参照される
Python では private や protected などのスコープを制御する機構は実装されておらず、クラス変数、インスタンス変数はすべてどこからでも参照可能(public)となります。
メソッド(method)
クラスが持つ関数は メソッド と呼ばれます。メソッドもまた、どこからでも参照可能(public)です。メソッドの第一引数には、クラスのインスタンスを指定し、第二引数以降で、メソッドの引数を受け取ります。
class MyClass:
name = ""
def setName(self, name): # 第一引数は自インスタンス(self)
self.name = name
a = MyClass()
a.setName("Tanaka")
アクセス制限(_, __)
Python では private や protected などのアクセス修飾子はサポートされていません。アンダーバー(_)で始まる変数や関数は外から参照しないという慣習的ルールがあります。アンダーバー2個(__)で始まる変数や関数は参照が制限されます。
class MyClass:
def __init__(self):
self.name = "tanaka"
self._name = "yamada"
self.__name = "suzuki"
def hello(self): print('hello')
def _hello(self): print('hello')
def __hello(self): print('hello')
a = MyClass()
print(a.name) # 参照できる
print(a._name) # 参照できるが慣習的に参照しない
# print(a.__name) # 参照できない(AttributeError例外)
a.hello() # 参照できる
a._hello() # 参照できるが慣習的に参照しない
# a.__hello() # 参照できない(AttributeError例外)
とは言っても、__ で始まる変数や関数も、_クラス名__変数名 に名前変換されるだけで、下記の様にするとアクセスできてしまうそうです。
print(a._MyClass__name) a._MyClass__hello()
コンストラクタ(__init__)
__init__() メソッドは、クラスのインスタンスが生成された際に呼び出されます。コンストラクタ とも呼ばれます。
class MyClass:
def __init__(self, name):
self.name = name
def getName(self):
return self.name
a = MyClass("Tanaka")
print(a.getName()) #=> Tanaka
デストラクタ(__del__)
__del__() メソッドは、クラスのインスタンスが消滅する際に呼び出されます。デストラクタ とも呼ばれます。
class MyClass:
def __init__(self):
print("INIT!")
def __del__(self):
print("DEL!")
a = MyClass() #=> INIT!
del a #=> DEL!
文字列化(__str__)
__str__() は、インスタンスを暗黙的に文字列に変換する際の変換処理を定義します。
class MyClass:
def __init__(self, name):
self.name = name
def __str__(self):
return "My name is " + self.name
a = MyClass("Yamada")
print(a) #=> My name is Yamada
継承(inheritance)
他のオブジェクト指向言語と同様、クラスを継承することもできます。下記の例では、MyClassクラスを継承した、MyClass2サブクラスを定義しています。サブクラスでは、親クラスが持つアトリビュートやメソッドを継承して利用することができます。
class MyClass:
def hello(self):
print("Hello")
class MyClass2(MyClass):
def world(self):
print("World")
a = MyClass2()
a.hello() #=> Hello
a.world() #=> World
サブクラスでは、親クラスのメソッドを上書き(オーバーライド)することができます。
class MyClass:
def hello(self):
print("Hello")
class MyClass2(MyClass):
def hello(self): # 親クラスのhello()メソッドをオーバーライド
print("HELLO")
a = MyClass2()
a.hello() #=> HELLO
親クラス(super())
super() は 親クラス を参照します。第一引数にはクラス、第二引数にはインスタンスを指定します。下記の例では、サブクラスのコンストラクタの中で、親クラスのコンストラクタを呼び出しています。
class MyClass1(object):
def __init__(self):
self.val1 = 123
class MyClass2(MyClass1):
def __init__(self):
super(MyClass2, self).__init__()
self.val2 = 456
a = MyClass2()
print(a.val1) #=> 123
print(a.val2) #=> 456
多重継承
Python では多重継承がサポートされています。下記では、MyClassA, MyClassB 両方を継承する MyClassC を定義しています。
class MyClassA:
def funcA(self):
print("MyClassA:funcA")
class MyClassB:
def funcB(self):
print("MyClassB:funcB")
class MyClassC(MyClassA, MyClassB):
pass
a = MyClassC()
a.funcA() # MyClassA のメソッドも
a.funcB() # MyClassB のメソッドも使用できる
クラス階層
Python のクラスはすべて、object をルートとするクラス階層を構成しています。
object
+- int
| +- bool
+- long
+- float
+- complex
+- basestring
| +- str
| +- unicode
+- list
+- tuple
+- dict
+- file
+- BaseException
+- SystemExit
+- KeyboardInterrupt
+- GeneratorExit
+- Exception
+- StopIteration
+- StandardError
| +- BufferError
| +- ArithmeticError
| | +- FloatingPointError
| | +- OverflowError
| | +- ZeroDivisionError
| +- AssertionError
| +- AttributeError
| +- EnvironmentError
| | +- IOError
| | +- OSError
| | +- WindowsError (Windows)
| | +- VMSError (VMS)
| +- EOFError
| +- ImportError
| +- LookupError
| | +- IndexError
| | +- KeyError
| +- MemoryError
| +- NameError
| | +- UnboundLocalError
| +- ReferenceError
| +- RuntimeError
| | +- NotImplementedError
| +- SyntaxError
| | +- IndentationError
| | +- TabError
| +- SystemError
| +- TypeError
| +- ValueError
| +- UnicodeError
| +- UnicodeDecodeError
| +- UnicodeEncodeError
| +- UnicodeTranslateError
+- Warning
+- DeprecationWarning
+- PendingDeprecationWarning
+- RuntimeWarning
+- SyntaxWarning
+- UserWarning
+- FutureWarning
+- ImportWarning
+- UnicodeWarning
+- BytesWarning