11
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

python黒魔術

Last updated at Posted at 2025-12-14

Python黒魔術

こういうイメージもってませんか?

  1. Pythonは誰が書いても同じようになる
  2. Pythonは初心者向けだ
  3. 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

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)

これで定義されていないはずのグローバル変数やビルトイン関数が変わります。酷い!

黒魔術を何に使うか

あえていおう、黒魔術は外道であると。

でも、知っている事自体はいいことだと思いますし、フレームワーク的なものを作る時におもしろい事ができたりはします。
というか、フレームワーク作る時以外に何か使いみちあるのかな…?

11
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?