Python 3.5.1でクラスを試す
- クラスのサンプル
- インスタンス生成で __init__ が呼ばれる
- with文で __enter__, __exit__ が呼ばれる
- for文で __iter__ が呼ばれる
- クラスのインスタンスオブジェクトのメソッド(インスタンス変数へアクセス可)
- クラスメソッド(インスタンス変数へはアクセス出来ない)
- スタティックメソッド(インスタンス変数へはアクセス出来ない)
- スクリプト終了で __del__ が呼ばれる
- メソッド名はどのように確認する?
- 行番号はどのように確認する?
クラスのサンプル
- Pythonのクラスは、PHPと異なりメソッドの第1引数に毎回
self
と書く必要があったりするようです。 - メソッドやクラス変数の
protected
,private
などのアクセス権はPythonには無いようです。 - 参考: Python チュートリアル クラス
# -*- encoding: utf-8 -*- import inspect, sys class Example: test = None # コンストラクタ def __init__(self): self.test = 'hoge' print(sys._getframe().f_code.co_name) print() # デストラクタ def __del__(self): print(sys._getframe().f_code.co_name) print() # with文の始め def __enter__(self): print(sys._getframe().f_code.co_name) print() # with ~ as 変数にインスタンスを格納する際に必要 return self # with文の終わり def __exit__(self, exc_type, exc_value, traceback): print(exc_type, exc_value, traceback) print(sys._getframe().f_code.co_name) print() # ジェネレータ def __iter__(self): print(sys._getframe().f_code.co_name) for i in range(10): yield i # クラスのインスタンスオブジェクトのメソッド # 第1引数に`self` def instance_method(self, *params): print(self.test) print(params) print(sys._getframe().f_code.co_name) print() # クラスメソッド @classmethod def class_methos(*params): print(params) print(sys._getframe().f_code.co_name) print() # スタティックメソッド @staticmethod def static_method(*params): print(params) print(sys._getframe().f_code.co_name) print()
インスタンス生成で __init__
が呼ばれる
- クラスのサンプルから抜粋
# コンストラクタ def __init__(self): self.test = 'hoge' print(sys._getframe().f_code.co_name) print()
- 実行した場合
e = Example() # __init__ が出力される
sys._getframe().f_code.co_name
でメソッド名を取得しています。
メソッド名はどのように確認する?
with文で __enter__
, __exit__
が呼ばれる
- クラスのサンプルから抜粋
# with文の始め def __enter__(self): print(sys._getframe().f_code.co_name) print() # with ~ as 変数にインスタンスを格納する際に必要 return self # with文の終わり def __exit__(self, exc_type, exc_value, traceback): print(exc_type, exc_value, traceback) print(sys._getframe().f_code.co_name) print()
- 実行した場合
with e as instance: # __enter__ が出力される print(instance) # __enter__ で self を return していないと None # with文が終了すると __exit__ が出力される
- これは、ファイルを開くときなどの形ですね。
with open('text.txt') as f: for line in f: pass
for文で __iter__
が呼ばれる
- クラスのサンプルから抜粋
# ジェネレータ def __iter__(self): print(sys._getframe().f_code.co_name) for i in range(10): yield i
- 実行した場合
print(', '.join([str(i) for i in e])) print() # __iter__ が出力され、 # __iter__ からの結果をリスト化し', 'でjoinして 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 を出力
- 参考:
クラスのインスタンスオブジェクトのメソッド(インスタンス変数へアクセス可)
直接も呼べますが、インスタンス変数へはアクセス出来ません
- クラスのサンプルから抜粋
# クラスのインスタンスオブジェクトのメソッド # 第1引数に`self` def instance_method(self, *params): print(self.test) print(params) print(sys._getframe().f_code.co_name) print()
- 実行した場合
e.instance_method(inspect.getouterframes(inspect.currentframe())[0].lineno) # hoge # __init__ で代入した値を出力 # (74,) # 行番号 # instance_method
inspect.getouterframes(inspect.currentframe())[0].lineno
で行番号を取得しています。
行番号はどのように確認する?
クラスメソッド(インスタンス変数へはアクセス出来ない)
インスタンスからも呼べますが、インスタンス変数へはアクセス出来ません
- クラスのサンプルから抜粋
@classmethod
というデコレータなる仕組みがポイントになるようです。
# クラスメソッド @classmethod def class_methos(*params): print(params) print(sys._getframe().f_code.co_name) print()
- 実行した場合
Example.class_methos(inspect.getouterframes(inspect.currentframe())[0].lineno) # (<class '__main__.Example'>, 78) # 行番号は第2引数に渡されている # class_methos
- 参考:
スタティックメソッド(インスタンス変数へはアクセス出来ない)
インスタンスからも呼べますが、インスタンス変数へはアクセス出来ません
- クラスのサンプルから抜粋
@staticmethod
というデコレータなる仕組みがポイントになるようです。
# スタティックメソッド @staticmethod def static_method(*params): print(params) print(sys._getframe().f_code.co_name) print()
- 実行した場合
Example.static_method(inspect.getouterframes(inspect.currentframe())[0].lineno) # (82,) # 行番号 # static_method
スクリプト終了で __del__
が呼ばれる
- クラスのサンプルから抜粋
# デストラクタ def __del__(self): print(sys._getframe().f_code.co_name) print()
- 実行した場合
# スクリプト終了直前に __del__ が出力される
- ガーベージコレクト任せになってしまい任意のタイミングに処理されるかどうかわからないため、
__enter__
,__exit__
によるwith文の方が扱いやすいようです。
メソッド名はどのように確認する?
PHPだと__FUNCTION__
で確認できるメソッド名は、Pythonだとsys._getframe().f_code.co_name
で確認できるようです。
- 参考:
行番号はどのように確認する?
PHPだと__LINE__
で確認できる行番号は、Pythonだとinspect.getouterframes(inspect.currentframe())[0].lineno
で確認できるようですが、バージョンによって少し異なるようです。今回はPython 3.5.1です。
- 参考: