> On Nov 22, 2014, at 2:45 PM, Chris Angelico <ros...@gmail.com> wrote: > > Does your middleware_generator work with just a single element, > yielding either one output value or none?
I apologize if I didn't make the point clearly. The middleware example was just simple outline of calling next(), doing some processing, and yielding a result while letting the StopIteration float through from the next() call. It was meant to show in summary form a pattern for legitimate uses of next() inside a generator. Some of those uses benefit from letting their StopIteration pass through rather than being caught, returning, and reraising the StopIteration. The worry is that your proposal intentionally breaks that code which is currently bug free, clean, fast, stable, and relying on a part of the API that has been guaranteed and documented from day one. Since the middleware() example was ineffective in communicating the need, here are some real-world examples. Here's one from Fredrick Lundh's ElementTree code in the standard library (there are several other examples besides this one in his code are well): def iterfind(elem, path, namespaces=None): # compile selector pattern cache_key = (path, None if namespaces is None else tuple(sorted(namespaces.items()))) if path[-1:] == "/": path = path + "*" # implicit all (FIXME: keep this?) try: selector = _cache[cache_key] except KeyError: if len(_cache) > 100: _cache.clear() if path[:1] == "/": raise SyntaxError("cannot use absolute path on element") next = iter(xpath_tokenizer(path, namespaces)).__next__ token = next() selector = [] while 1: try: selector.append(ops[token[0]](next, token)) except StopIteration: raise SyntaxError("invalid path") try: token = next() if token[0] == "/": token = next() except StopIteration: break _cache[cache_key] = selector # execute selector pattern result = [elem] context = _SelectorContext(elem) for select in selector: result = select(context, result) return result And here is an example from the pure python version of one of the itertools: def accumulate(iterable, func=operator.add): 'Return running totals' # accumulate([1,2,3,4,5]) --> 1 3 6 10 15 # accumulate([1,2,3,4,5], operator.mul) --> 1 2 6 24 120 it = iter(iterable) total = next(it) yield total for element in it: total = func(total, element) yield total And here is an example from Django: def _generator(): it = iter(text.split(' ')) word = next(it) yield word pos = len(word) - word.rfind('\n') - 1 for word in it: if "\n" in word: lines = word.split('\n') else: lines = (word,) pos += len(lines[0]) + 1 if pos > width: yield '\n' pos = len(lines[-1]) else: yield ' ' if len(lines) > 1: pos = len(lines[-1]) yield word return ''.join(_generator()) I could scan for even more examples, but I think you get the gist. All I'm asking is that you consider that your proposal will do more harm than good. It doesn't add any new capability at all. It just kills some code that currently works. Raymond (the author of the generator expressions pep)
_______________________________________________ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com