python - Override list's builtins dynamically in class scope -
purely curiosity question:
class li(list): pass m, n= li([1]), li([2]) def r(*args, **kwargs): raise exception('hop') setattr(m, '__iadd__', r) m += n print m # [1, 2] setattr(li, '__iadd__', r) m += n output:
[1, 2] traceback (most recent call last): file "c:\...\test_override.py", line 8, in <module> m+=n file "c:\...\test_override.py", line 3, in r def r(*args, **kwargs): raise exception('hop') exception: hop if use setattr(m, 'append', r) m.append(2) fail. __iadd__ called on class object ?
also can use settattr class scope ? naive attempt in:
def r(*args, **kwargs): raise exception('hop') class li(list): s in {'__iadd__','append'}: setattr(li, s, r) fails nameerror: name 'li' not defined
in new style classes, instance __getattr__ method no longer intercepts calls made built-in operations. when built-in operation used, search begins @ class level instead of @ instance level. nevertheless, explicit call method name work:
>>> class li(list): pass >>> m, n= li([1]), li([2]) >>> def r(*args, **kwargs): raise exception('hop') >>> setattr(m, '__iadd__', r) >>> m += n # no exception raised >>> m.__iadd__(n) # explicitly calling method searches instance first traceback (most recent call last): file "<pyshell#76>", line 1, in <module> m.__iadd__(n) file "<pyshell#73>", line 1, in r def r(*args, **kwargs): raise exception('hop') exception: hop one way accomplish second goal use a metaclass, if want create attributes once (as per comments):
>>> class meta(type): def __new__(meta, name, bases, attrdict): print 'adding class attributes!' s in {'__iadd__','append'}: attrdict[s] = r return super(meta, meta).__new__(meta, name, bases, attrdict) def __init__(cls, name, bases, attrdict): super(meta, cls).__init__(name, bases, attrdict) >>> class li(list): __metaclass__ = meta adding class attributes! # attributes added here >>> t = li() # not on instance creation >>> li.__dict__ dict_proxy({'__module__': '__main__', '__metaclass__': <class '__main__.meta'>, '__iadd__': <function r @ 0x02aaa270>, '__dict__': <attribute '__dict__' of 'li' objects>, '__weakref__': <attribute '__weakref__' of 'li' objects>, '__doc__': none, 'append': <function r @ 0x02aaa270>})
Comments
Post a Comment