On Thu, Jan 31, 2013 at 12:46 AM, Steven D'Aprano < steve+comp.lang.pyt...@pearwood.info> wrote:
> On Wed, 30 Jan 2013 19:34:03 -0500, Jason Swails wrote: > > > Hello, > > > > I was having some trouble understanding decorators and inheritance and > > all that. This is what I was trying to do: > > > > # untested > > class A(object): > > def _protector_decorator(fcn): > > def newfcn(self, *args, **kwargs): > > return fcn(self, *args, **kwargs) > > return newfcn > > Well, that surely isn't going to work, because it always decorates the > same function, the global "fcn". > I don't think this is right. fcn is a passed function (at least if it acts as a decorator) that is declared locally in the _protector_decorator scope. Since newfcn is bound in the same scope and fcn is not defined inside newfcn, I'm pretty sure that newfcn will just grab the fcn passed into the decorator. The following code illustrates what I'm trying to say (I think): test.py: #!/usr/bin/env python a = 3 print 'Global namespace:', a def myfunc(a): def nested_func(): print 'nested_func a is:', a, 'id(a) =', id(a) print 'passed a is:', a, 'id(a) = ', id(a) nested_func() myfunc(10) $ python test.py Global namespace: 3 passed a is: 10 id(a) = 6416096 nested_func a is: 10 id(a) = 6416096 Likewise, newfcn will use the function bound to the passed argument to the decorator. This syntax appears to work in my 'real' program. > You probably want to add an extra parameter to the newfcn definition: > > def newfcn(self, fcn, *args, **kwargs): > I don't think I want to do that, since fcn will simply become the first argument that I pass to the decorated myfunc(), and if it's not callable I'll get a traceback. Also, I trust you realise that this is a pointless decorator that doesn't > do anything useful? It just adds an extra layer of indirection, without > adding any functionality. > Naturally. I tried to contrive the simplest example to demonstrate what I wanted. In retrospect I should've picked something functional instead. > Am I correct here? My workaround was to simply copy the method from > > class A to class B, after which B._protector_decorator decorated the > > methods in B. > > That's not a work-around, that's an anti-pattern. > > Why is B inheriting from A if you don't want it to be able to use A's > methods? That's completely crazy, if you don't mind me saying so. If you > don't want B to access A's methods, simply don't inherit from A. > > I really don't understand what you are trying to accomplish here. > Again, my example code is over-simplified. A brief description of my class is a list of 'patch' (diff) files with various attributes. If I want information from any of those files, I instantiate a Patch instance (and cache it for later use if desired) and return any of the information I want from that patch (like when it was created, who created it, what files will be altered in the patch, etc.). But a lot of these patches are stored online, so I wanted a new class (a RemotePatchList) to handle lists of patches in an online repository. I can do many of the things with an online patch that I can with one stored locally, but not everything, hence my desire to squash the methods I don't want to support. I'd imagine a much more sensible approach is to generate a base class that implements all methods common to both and simply raises an exception in those methods that aren't. I agree it doesn't make much sense to inherit from an object that has MORE functionality than you want. However, my desire to use decorators was not to disable methods in one class vs. another. The _protector_decorator (a name borrowed from my actual code), is designed to wrap a function call inside a try/except, to account for specific exceptions I might raise inside. One of my classes deals with local file objects, and the other deals with remote file objects via urllib. Naturally, the latter has other exceptions that can be raised, like HTTPError and the like. So my desire was to override the decorator to handle more types of exceptions, but leave the underlying methods intact without duplicating them. I can do this without decorators easily enough, but I thought the decorator syntax was a bit more elegant and I saw an opportunity to learn more about them. Possibly Java. > I took a Java class in high school once ~10 years ago... haven't used it since. :) Truth be told, outside of Python, the languages I can work in are Fortran (and to a much lesser extent), C and C++. import functools > I need to support Python 2.4, and the docs suggest this is 2.5+. Too bad, too, since functools appears pretty useful. Thanks for the help! Jason
-- http://mail.python.org/mailman/listinfo/python-list