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

Popular posts from this blog

shopping cart - Page redirect not working PHP -

php - How to modify a menu to show sub-menus -

python - Installing PyDev in eclipse is failed -