Steven D'Aprano wrote: > On Wednesday 14 December 2016 17:11, Veek M wrote: > >> I know that with user classes one can define getattr, setattr to >> handle dictionary lookup. Is there a way to hook into the native >> dict() type and see in real time what's being queried. > > Not easily, and maybe not at all. > > There are two obvious ways to do this: > > (1) monkey-patch the object's __dict__, and the class __dict__. > > Unfortunately, Python doesn't support monkey-patching built-ins. > > https://en.wikipedia.org/wiki/Monkey_patch > > Or perhaps I should say, *fortunately* Python doesn't support it. > > http://www.virtuouscode.com/2008/02/23/why-monkeypatching-is-destroying-ruby/ > > (2) Alternatively, you could make a dict subclass, and replace the > class and instance __dict__ with your own. > > Unfortunately, you cannot replace the __dict__ of a class: > > py> class X: # the class you want to hook into > ... pass > ... > py> class MyDict(dict): # my custom dict > ... def __getitem__(self, key): > ... print(key) > ... return super().__getitem__(key) > ... > py> d = MyDict() > py> d.update(X.__dict__) > py> X.__dict__ = d > Traceback (most recent call last): > File "<stdin>", line 1, in <module> > AttributeError: attribute '__dict__' of 'type' objects is not writable > > > You can replace the instance dict, but Python won't call your > __getitem__ method: > > py> instance = X() > py> instance.__dict__ = MyDict() > py> instance.a = 999 > py> instance.a > 999 > > So the short answer is, No. > > You might be able to create a completely new metaclass that supports > this, but it would be a lot of work, and I'm not even sure that it > would be successful. > > > >> I wanted to check if when one does: >> >> x.sin() >> >> if the x.__dict__ was queried or if the Foo.__dict__ was queried.. > > The easiest way to do that is something like this: > > > py> class Test: > ... def sin(self): > ... return 999 > ... > py> x = Test() > py> x.sin > <bound method Test.sin of <__main__.Test object at 0xb6fc3a4c>> > py> x.sin() > 999 > py> x.sin = "surprise!" > py> x.sin > 'surprise!' > > > > So now you know: an instance attribute will shadow the class > attribute. > > (Actually, that's not *completely* true. It depends on whether x.sin > is a descriptor or not, and if so, what kind of descriptor.) > >
heh If it walks like a duck and talks like a duck, it’s a duck, right? So if this duck is not giving you the noise that you want, you’ve got to just punch that duck until it returns what you expect. -Patrick Ewing on Monkey/Duck patching in RailsConf 2007 -- https://mail.python.org/mailman/listinfo/python-list