On Tue, 22 Nov 2005, Steven D'Aprano wrote: > Are there practical idioms for solving the metaproblem "solve problem X > using the latest features where available, otherwise fall back on older, > less powerful features"? > > For instance, perhaps I might do this: > > try: > built_in_feature > except NameError: > # fall back on a work-around > from backwards_compatibility import \ > feature as built_in_feature > > Do people do this or is it a bad idea?
>From some code i wrote yesterday, which has to run under 2.2: try: True except NameError: True = 1 == 1 False = 1 == 0 Great minds think alike! As for whether it's a bad idea, well, bad or not, it certainly seems like the least worst. > Are there other techniques to use? Obviously refusing to run is a > solution (for some meaning of "solution"), it may even be a practical > solution for some cases, but is it the only one? How about detecting which environment you're in, then running one of two entirely different sets of code? Rather than trying to construct modern features in the antique environment, write code for each, using the local idioms. The trouble with this is that you end up with massive duplication; you can try to factor out the common parts, but i suspect that the differing parts will be a very large fraction of the codebase. > If I have to write code that can't rely on iter() existing in the > language, what should I do? Can you implement your own iter()? I have no idea what python 2.0 was like, but would something like this work: class _iterator: def __init__(self, x): self.x = x self.j = 0 def next(self): self.j = self.j + 1 return self.x.next() def __getitem__(self, i): if (i != self.j): raise ValueError, "out of order iteration" try: return self.next() except StopIteration: raise IndexError def __iter__(self): return self # hopefully, we don't need this, but if we do ... def __len__(self): return sys.maxint # and rely on StopIteration to stop the loop class _listiterator(_iterator): def next(self): try: item = self.x[self.j] self.j = self.j + 1 return item except IndexError: raise StopIteration def __getitem__(self, i): if (i != self.j): raise ValueError, "out of order iteration" self.j = self.j + 1 return self.x[i] import types def iter(x): # if there's no hasattr, use explicit access and try-except blocks # handle iterators and iterables from the future if hasattr(x, "__iter__"): return _iterator(x.__iter__()) # if there's no __getitem__ on lists, try x[0] and catch the exception # but leave the __getitem__ test to catch objects from the future if hasattr(x, "__getitem__"): return _listiterator(x) if type(x) == types.FileType: return _fileiterator(x) # you can imagine the implementation of this # insert more tests for specific types here as you like raise TypeError, "iteration over non-sequence" ? NB haven't actually tried to run that code. tom -- I'm angry, but not Milk and Cheese angry. -- Mike Froggatt -- http://mail.python.org/mailman/listinfo/python-list