On Mon, 13 Mar 2006 21:28:06 -0800, garyjefferson123 wrote: > I'm having a scoping problem. I have a module called SpecialFile, > which defines: > > def open(fname, mode): > return SpecialFile(fname, mode)
This is called "shadowing a built-in", and generally speaking it causes Bad Things To Happen. The secret to avoiding those Bad Things is to not shadow built-ins. This isn't a hard and fast rule, but as a good general principle, if you have to ask "How do I avoid this problem?", you shouldn't be using shadowing. (Think of it this way: if you have to ask "How do I avoid being horribly injured when I crash my car into a wall at 90mph?", you shouldn't be crashing your car into a wall at 90mph. Yes, I know that makes the bootstrapping problem difficult for those budding stunt men and women who want to learn, but they generally manage. And most of the time they manage by not actually crashing their car into a wall at 90mph -- they find a better way to get the same effect.) > class SpecialFile: > > def __init__(self, fname, mode): > self.f = open(fname, mode) > ... > > > The problem, if it isn't obvioius, is that the open() call in __init__ > no longer refers to the builtin open(), but to the module open(). In your code, open() is not a module, it is a function. A better technique will be to turn open into a method of the class SpecialFile, rather than a bare function. That way you keep open() the built-in function separate from SpecialFile.open(). > So, if I do: > > f = SpecialFile.open(name, mode) > > I get infinite recursion. I see you are already using an open method. So let me see if I have this right: you have a function open, plus an open method? Why? As near as I can tell, you have a function called "open" which returns a SpecialFile instance. I don't understand why you would want to do that -- it seems like a poor API design to me. But maybe there's something I don't understand. It looks like you are expecting to do this: file = open('data.txt', 'r') # file is now an automatically opened SpecialFile. This is bad design because it isn't clear that you have done something special. It *looks* like you have just opened an ordinary file, and unless you study the entire module, you wouldn't have any clue that in fact you have opened a SpecialFile instead. I would handle it like this: class SpecialFile(object): def __init__(self, fname, mode='r'): self.fname = fname self.mode = mode def open(self): self.f = open(self.fname, self.mode) def close(self): self.f.close() def read(self): return self.f.read() def write(self, data): self.f.write(data) You use it like so: sf = SpecialFile("hello.txt") sf.open() data = sf.read() sf.close() (Actually, I wouldn't handle it like this at all, unless a SpecialFile did things that an ordinary file didn't. But presumably you have something special in mind.) This, in my opinion, is a better solution. You don't have to jump through hoops to get back at the built-in version of open, and the code is self-documenting: to open a SpecialFile, you ask for a SpecialFile. -- Steven. -- http://mail.python.org/mailman/listinfo/python-list