Más contenido relacionado
La actualidad más candente (20)
Pythonによる黒魔術入門
- 9. 諸注意
黒魔術が比較的易しい and 頻出 and メジャーな言語、などの理由から
今回の説明に使う言語はPythonです(筆者の知識の問題もあります)。
マクロについては、筆者のLisp力や抽象構文木に対する理解度不足などの
事情があるので今回は取り扱いません。
比較的に易しい内容を取り扱う予定ですが、最低限のオブジェクト指向と
その言語内実装に対する理解度はあった方が良いかもしれません。
- 11. Ghost Method
サンプルコード(動的な委譲)
>>> class DynamicProxy(object):
... def __init__(self, value):
... self._value = value
...
... def __getattr__(self, name):
... return getattr(self._value, name)
...
!
>>> proc = DynamicProxy('hoge')
>>> proc.title()
'Hoge'
- 16. サンプルコード(動的な委譲)
>>> from operator import methodcaller
!
>>> class NullSafeContainer(object):
... def __getattr__(self, name):
... def _(targ):
... if targ is None:
... return lambda *args, **kw: None
... return lambda *args, **kw: methodcaller(name,
*args, **kw)(targ)
... return _
...
>>> ns = NullSafeContainer()
>>> ns.replace('foo bar baz')('bar', 'gege')
'foo gege baz'
>>> ns.replace(None)('bar', 'gege')
- 19. Monkey Patch
サンプルコード(動的な委譲)
>>> class Container(object):
... pass
...
>>> c = Container()
!
>>> def new_method(self, val):
... return val
...
>>> # setattr(Container, 'new_method', new_method)
>>> Container.new_method = new_method
>>> c.new_method('new!')
'new!'
- 21. 以下蛇足
Pythonではインスタンスへの動的なメソッド追加は出来ない。
>>> def new_instance_method(self, val):
... return 'in instance "{0}"'.format(val)
...
>>> # c.new_instance_method = new_instance_method
>>> setattr(c, 'new_instance_method', new_instance_method)
>>> c.new_instance_method('new!')
Traceback (most recent call last):
...
TypeError: new_instance_method() takes exactly 2 arguments
(1 given)
- 26. Meta Class その前に
クラスの動的な生成
>>> MyClass = type(
... 'MyClass',
... (object, ),
... {
... '__init__': lambda self, val: setattr(self,
'_val', val),
... 'say': lambda self: self._val,
... },
... )
>>> mc = MyClass('aaa')
>>> mc.say()
'aaa'
- 30. メタクラスの活用例
>>> def _logging_hook(func):
... def __(*args, **kw):
... print('before: {0}'.format(func.__name__))
... ret = func(*args, **kw)
... print('after: {0}'.format(func.__name__))
... return ret
... return __
...
次ページへつづく
こういう関数を用意しておいて……
- 31. >>> from types import (
... MethodType, FunctionType, LambdaType
... )
>>> class LoggingHookKlass(type):
... def __new__(cls, name, bases, dict):
... hooked_attrs = {
... k: _logging_hook(v)
... for k, v in dict.items()
... if isinstance(v, (MethodType, FunctionType,
LambdaType))
... }
... return type.__new__(cls, name, bases, hooked_attrs)
次ページへつづく
こういうメタクラスを作って
- 32. >>> class Ninja(object):
... __metaclass__ = LoggingHookKlass
... def aisatsu(self, other):
... print(‘ドーモ、{0}=サン’.format(other))
...
>>> ninja = Ninja()
>>> ninja.aisatsu('オフェンダー')
before: aisatsu
ドーモ、オフェンダー=サン
after: aisatsu
次ページで解説
こう使う