Python黒魔術
こういうイメージもってませんか?
- Pythonは誰が書いても同じようになる
- Pythonは初心者向けだ
- Pythonは変なものではない
しかし、敢えて言おう!pythonにも外道があると!
python今回はpython黒魔術と僕の考える応用を書きつらねてみようと思います。
特殊メソッド
クラスを作る時に特殊なメソッドを作る事ができます。まー、これはpythonを書く人にはおなじみだから大した事はないですね。ただ__getattr__なんかは凄く暗黒っぽいですね。
メンバー変数が無い場合にこれを返す事ができます。すごいですね。
例えばこんな感じですね。
class Hoge:
def __init__(self):
self.data = 3
def __add__(self, x):
self.data += x.data
return self
def __repr__(self):
print(f'[{self.data}]')
def __getattr__(self, name):
'''
メンバー変数が無い場合呼ぶ
'''
return '未定義'
hoge = Hoge()
print(hoge + hoge)
print(hoge.hoge)
print(hoge.fuga)
メタクラス
Pythonのclassとはなにか?
pythonのclassはtypeのインスタンスです。
こんな感じですね。
- type
- class
- instance
- class
typeの具体的なのがclass、classの具体的なのがinstanceです。ということは何が起るかというと「classを作る時に作り型をカスタマイズできる」という事です。
具体的に
クラスからインスタンスを作る時には例えばHoge()とかしますよね?という事はHoge()の__call__()特殊メソッドをカスタマイズすればいいわけです。あとはmetaclassという引数としてわたせばいいのです。
例えばシングルトンを作る場合は下記のようにすればいいのですね。
class Hoge:
pass
class SingletonMeta(type):
_instance = None
def __call__(cls, *args, **kwargs):
if cls._instance is None:
cls._instance = super().__call__(*args, **kwargs)
return cls._instance
class Singleton(metaclass=SingletonMeta):
pass
class Fuga(Singleton):
pass
print(Hoge() == Hoge())
print(Fuga() == Fuga())
エラーのカスタマイズ
Pythonのエラーはカスタマイズする事ができます。通常はhookを使う事になります。
以前、Pythonのエラーをほぼ全てずんだもん化するpython packageを作った事があります。
import sys
def _exception_hook(cls, er, tb):
if cls is ZeroDivisionError:
print(f'ゼロで割り算してはいけないのだ!')
sys.excepthook = _exception_hook
4 / 0
こんな感じでエラーを弄る事ができちゃうんですね。
Global変数を弄る
非明示的にGlobal変数を弄る事ができます。これは、正直悪用する以外の用途が思いつかない…。例えばこのようなmusuka.pyを作って…
import builtins
def musuka(*args):
try:
_hidden_print(f'見ろ!{args[0].__name__}がゴミのようだ!')
except:
_hidden_print(f'見ろ!{args[0]}がゴミのようだ!')
_hidden_print = globals()['__builtins__']['print']
globals()['__builtins__']['print'] = musuka
globals()['__builtins__']['hoge'] = '未定義変数'
それをimportしてみましょう。
import muska
# 文字列
print('hoge')
# ビルトイン関数
print(input)
#
# 定義されていないはずの変数
print(hoge)
これで定義されていないはずのグローバル変数やビルトイン関数が変わります。酷い!
黒魔術を何に使うか
あえていおう、黒魔術は外道であると。
でも、知っている事自体はいいことだと思いますし、フレームワーク的なものを作る時におもしろい事ができたりはします。
というか、フレームワーク作る時以外に何か使いみちあるのかな…?