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,
Solution 1:
In new style classes, the instance __getattr__
method no longer intercepts calls made by built-in operations. When the built-in operation is used, the search begins at the class level instead of at the instance level. Nevertheless, an explicit call to the method name will work:
>>> classLi(list): pass>>> m, n= Li([1]), Li([2])
>>> defr(*args, **kwargs):
raise Exception('hop')
>>> setattr(m, '__iadd__', r)
>>> m += n # no exception raised>>> m.__iadd__(n) # explicitly calling the method searches the instance first
Traceback (most recent call last):
File "<pyshell#76>", line 1, in <module>
m.__iadd__(n)
File "<pyshell#73>", line 1, in r
defr(*args, **kwargs): raise Exception('hop')
Exception: hop
One way to accomplish your second goal is to use a metaclass, especially if you only want to create the attributes once (as per your comments):
>>> classMeta(type):
def__new__(meta, name, bases, attrdict):
print'adding class attributes!'for s in {'__iadd__','append'}:
attrdict[s] = r
returnsuper(Meta, meta).__new__(meta, name, bases, attrdict)
def__init__(cls, name, bases, attrdict):
super(Meta, cls).__init__(name, bases, attrdict)
>>> classLi(list):
__metaclass__ = Meta
adding classattributes! # attributes added here>>> t = Li() # but not on instance creation>>> Li.__dict__
dict_proxy({'__module__': '__main__', '__metaclass__': <class'__main__.Meta'>, '__iadd__': <function r at 0x02AAA270>, '__dict__': <attribute '__dict__' of 'Li' objects>, '__weakref__': <attribute '__weakref__' of 'Li' objects>, '__doc__': None, 'append': <function r at 0x02AAA270>})
Post a Comment for "Override List's Builtins Dynamically In Class Scope"