From: Ulrich Eckhardt on 10 Aug 2010 05:01 Hi! I have an extension module (a plugin written with Boost.Python) and around that a wrapper class that adapts a few things. Since the module is a plugin, there are multiple implementations of this. What I'm currently doing is this: plugin = __import__(plugin_name) class PluginWrapper(plugin.PluginClass): ... This means that the definition of class PluginWrapper actually depends on the previously loaded module. What I would like to do is to define the wrapper just once and instead pass the plugin module to the constructor: class PluginWrapper(object): ... plugin = __import__(plugin_name) instance = PluginWrapper(plugin) Now, I use the wrapper to make some function more friendly (e.g. default parameters, keyword-parameters, wrapping raw handles) but I want other functions from the baseclass to remain untouched. If I use a baseclass, this lookup is automatic. However, when I pass the instance to the constructor, I have to store it in a member, and then I have to add code for every function only to delegate it to that member. Is there an easy and generic way out of this? Thanks! Uli -- Sator Laser GmbH Geschäftsführer: Thorsten Föcking, Amtsgericht Hamburg HR B62 932
From: Peter Otten on 10 Aug 2010 05:12 Ulrich Eckhardt wrote: > Hi! > > I have an extension module (a plugin written with Boost.Python) and around > that a wrapper class that adapts a few things. Since the module is a > plugin, there are multiple implementations of this. What I'm currently > doing is this: > > plugin = __import__(plugin_name) > > class PluginWrapper(plugin.PluginClass): > ... > > This means that the definition of class PluginWrapper actually depends on > the previously loaded module. What I would like to do is to define the > wrapper just once and instead pass the plugin module to the constructor: > > class PluginWrapper(object): > ... > plugin = __import__(plugin_name) > instance = PluginWrapper(plugin) > > > Now, I use the wrapper to make some function more friendly (e.g. default > parameters, keyword-parameters, wrapping raw handles) but I want other > functions from the baseclass to remain untouched. If I use a baseclass, > this lookup is automatic. However, when I pass the instance to the > constructor, I have to store it in a member, and then I have to add code > for every function only to delegate it to that member. > > Is there an easy and generic way out of this? Use getattr() >>> class W(object): .... def __init__(self, wrapped): self._wrapped = wrapped .... def __getattr__(self, name): .... return getattr(self._wrapped, name) .... >>> class A(object): .... def hello(self): print "hello" .... >>> a = A() >>> w = W(a) >>> w.hello() hello However, with newsytle classes this doesn't work for __special__ methods >>> w.__str__() '<__main__.W object at 0x7f04ef2d4c50>' Peter
From: Chris Rebert on 10 Aug 2010 05:19 On Tue, Aug 10, 2010 at 2:01 AM, Ulrich Eckhardt <eckhardt(a)satorlaser.com> wrote: > Hi! > > I have an extension module (a plugin written with Boost.Python) and around > that a wrapper class that adapts a few things. Since the module is a > plugin, there are multiple implementations of this. What I'm currently > doing is this: > > Â plugin = __import__(plugin_name) > > Â class PluginWrapper(plugin.PluginClass): > Â Â ... > > This means that the definition of class PluginWrapper actually depends on > the previously loaded module. What I would like to do is to define the > wrapper just once and instead pass the plugin module to the constructor: > > Â class PluginWrapper(object): > Â Â ... > Â plugin = __import__(plugin_name) > Â instance = PluginWrapper(plugin) > > > Now, I use the wrapper to make some function more friendly (e.g. default > parameters, keyword-parameters, wrapping raw handles) but I want other > functions from the baseclass to remain untouched. If I use a baseclass, > this lookup is automatic. However, when I pass the instance to the > constructor, I have to store it in a member, and then I have to add code > for every function only to delegate it to that member. > > Is there an easy and generic way out of this? Create the subclass(es) dynamically: def wrap(plug_in): class PluginWrapper(plug_in.PluginClass): ... return PluginWrapper plugin = __import__(plugin_name) WrappedPlugin = wrap(plugin) Cheers, Chris -- http://blog.rebertia.com
From: Ulrich Eckhardt on 10 Aug 2010 06:40 Peter Otten wrote: > Use getattr() > >>>> class W(object): > ... def __init__(self, wrapped): self._wrapped = wrapped > ... def __getattr__(self, name): > ... return getattr(self._wrapped, name) > ... I thought there was something like this, thanks! :) When I read this, I thought "OK, now I only have check first if the attribute can be looked up in 'self' first", but even that isn't the case. I tried it and added another function to class W above, which I can call just as if it was defined in _wrapped, so obviously (?) the __getattr__ lookup isn't done there. So, short follow-up question: Why does this work? Uli -- Sator Laser GmbH Geschäftsführer: Thorsten Föcking, Amtsgericht Hamburg HR B62 932
From: Peter Otten on 10 Aug 2010 07:17 Ulrich Eckhardt wrote: > Peter Otten wrote: >> Use getattr() >> >>>>> class W(object): >> ... def __init__(self, wrapped): self._wrapped = wrapped >> ... def __getattr__(self, name): >> ... return getattr(self._wrapped, name) >> ... > > I thought there was something like this, thanks! :) > > When I read this, I thought "OK, now I only have check first if the > attribute can be looked up in 'self' first", but even that isn't the case. The getattr() call inside __getattr__() raises an AttributeError if it can't find an attribute called name in self._wrapped. This very thing you'd have to do if you wanted to signal that an attribute doesn't exist, like in >>> class A: .... def __getattr__(self, name): .... if name == "foo": return 42 .... raise AttributeError .... >>> a = A() >>> a.foo 42 >>> a.bar Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 4, in __getattr__ AttributeError > I tried it and added another function to class W above, which I can call > just as if it was defined in _wrapped, so obviously (?) the __getattr__ > lookup isn't done there. > > So, short follow-up question: Why does this work? __getattr__() is a fallback that is only tried when the normal lookup fails. If you need to intercept every attribute lookup use __getattribute__() instead: >> class A(object): .... def __getattr__(self, name): .... print "__getattr__(%r)" % name .... return 42 .... def __getattribute__(self, name): .... print "__getattribute__(%r)" % name .... return super(A, self).__getattribute__(name) .... >>> a = A() >>> a.foo = "yadda" >>> a.foo __getattribute__('foo') 'yadda' >>> a.bar __getattribute__('bar') __getattr__('bar') 42 Peter
|
Next
|
Last
Pages: 1 2 Prev: Using the print command in Python3 Next: MailingLogger 3.3.3 Released! |