Path: csiph.com!fu-berlin.de!uni-berlin.de!not-for-mail From: Stefan Schwarzer Newsgroups: de.comp.lang.python Subject: Re: [Python-de] =?utf-8?q?Syntax-Erweiterung_f=C3=BCr_Schleifen_in_P?= =?utf-8?q?ython3?= Date: Sun, 10 Apr 2016 10:24:35 +0200 Lines: 100 Message-ID: References: <5708ACF0.3030708@sschwarzer.net> <570A0DC3.50001@sschwarzer.net> Mime-Version: 1.0 Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 8bit X-Trace: news.uni-berlin.de VCEUszXg4VJiBrDciXPY9QxZ6sABn9joo+Z95i10ZKAg== Return-Path: X-Original-To: python-de@python.org Delivered-To: python-de@mail.python.org X-Enigmail-Draft-Status: N1110 User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.24) Gecko/20100411 Thunderbird/2.0.0.24 Mnenhy/0.7.6.666 In-Reply-To: X-Provags-ID: V03:K0:hf98m6ChJIBN9S2O1Y5n3a9Ul3mb1BaUo9T0rEM/o8luTir5Vjd t4rva2MnURu9cAnfykTJ0vRlICl6Xh0qm5OhcvUvRDP+5wND2n4RP5srttTt1JquyKtySOY +QGma+35m2xmV8A7fMw8xeqM0sNNNRGHcbsIFa4zwU0z/1e8lfiwiRcbr9cPB1bervI35SO 10Ps+f3JfnpMG9wITA/Ew== X-UI-Out-Filterresults: notjunk:1;V01:K0:zJH4MtS2bZc=:oATweuTU/tz5rRsp2LjV1v j/7O50f3MXGrnkOkH5caDF1RGcivlSFBP7BbMYLT+b4eI+0RFRs4Vk53Oy6zF/DXEAl41DTEE d4Gzd8XSCQ8KMsHMV6NSKzMu4wnhdV6J6js1c0AyvOHGR0NZzAY/P0unK6FE/vLpqJhq4MAvv 82C2DQjirAi0Kpgqak/L0RWmYi/rI6D5ziIeaFqXy/e/imXAV8fY+LieqL1Ras1flGmNdD4Zq Tvnl8+qwt3tkMeaFlhJlXMe/767yk9J/tJqn04XvXISw6BCuVJk10hRRVcIPucZXuDx4zfjp3 iGw7klxW2G7/zLqEIC3J5k4aDufspvWk1f2pkx7O+3mCDPsAqNF/N798n2JlKXUn758xEtKKp ZSauDqMUzIHLeq5pBe2ESDe6i6RaZZ++9j9I602W6PTS+cirUFKEz2ljmPEQ2pcY05T7jvygP Eps9P5u7Z8i2b1m87K7b8juM47fkaxedy/7qpl/Q5tJQI7Tiz4e/jbW2+lu6tk/QC8u71fkIa 2vSXKMukcl7slTVFjMp3JUoDX7Plv/VfZL54d2sehq1PXfOgfwY5FC/FRXUG8EBk3UyNwsIxF /urHZsGxpbUc83DwlGFEVxI4mVccNrlZdWjiUr2awJkuOyU3XTXEcPSW2AUsZyB8Ufw1DdiGs Slgu2EnT9aFFLIeuu36BuVD7n7NNM2nRXKytUdmNPnLTYt+jJUd9iCwjUO2J8RCupFM7aMpQO D2563mqNOx5C8mAL X-BeenThere: python-de@python.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: Die Deutsche Python Mailingliste List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Mailman-Original-Message-ID: <570A0DC3.50001@sschwarzer.net> X-Mailman-Original-References: <5708ACF0.3030708@sschwarzer.net> Xref: csiph.com de.comp.lang.python:4391 On 2016-04-09 12:54, Christian Tanzer wrote: > Stefan Schwarzer wrote at Sat, 9 Apr 2016 09:19:12 +0200: >> Ich habe darüber nachgedacht, aber mir ist kein besserer >> Ansatz eingefallen wie in den schon geschriebenen Antworten. >> >> Ein Kontextmanager fällt aus, da bei einem `with`-Statement >> der Block nur einmal durchlaufen werden kann. >> >> Den Schleifenrumpf zu einer Funktion zu machen und in eine >> Higher-Order-Function hineinzureichen wird deutlich >> komplizierter als der schon beschriebene Ansatz mit Flag >> oder Sentinel. >> >> Fällt euch noch etwas ein? > > Sicher. Generator-Funktionen sind das Mittel der Wahl, um sowas zu > abstrahieren. Christian, du hast natürlich recht, dass man bei Verwendung einer Generator-Funktion keine Funktion für den Schleifenrumpf übergeben muss. > [Generator-Code-Beispiel] Aber auch mit einer Generator-Funktion habe ich Zweifel, dass sich mit einer derart abstrahierten API der diskutierte Anwendungsfall vereinfacht. Der Ausgangspunkt war: item = unset = object() for item in iterable: ... if item is unset: code_if_iterable_is_empty Eine Generator-Funktion, die das abstrahiert, könnte dann so aussehen: def iter_if_not_empty(iterable, if_empty_func): it = iter(iterable) try: first = next(it) except StopIteration: if_empty_func() else: yield first yield from it und deren Anwendung so: def my_if_empty(): code_if_iterable_is_empty for item in iter_if_not_empty(iterable, my_if_empty): ... Wenn `my_if_empty` inline for der Schleife definiert wird, muss man nicht zwingend Parameter übergeben, ansonsten kämen noch `*if_empty_args` und `**if_empty_kwargs` dazu, die an `iter_if_not_empty` übergeben und in `iter_if_not_empty` beim Aufruf von `if_empty_func` übergeben werden müssten. Wenn `my_if_empty` den lokalen Namespace modifizieren will, in dem die Schleife (`for item in iter_if_not_empty(...)`) steht, muss `my_if_empty` zusätzliche eine `nonlocal`-Anwendung enthalten (die es zudem erst in Python 3 gibt). Alles in allem bin ich nicht überzeugt, dass es eine API gibt, mit der sich die ursprüngliche Anwendung annähernd so geradlinig implementieren lässt. Mit anderen Worten: die API (`iter_if_not_empty` und Extra-Definition einer `if_empty`-Funktion) verbessert aus meiner Sicht die Lage nicht. Was mich an dem Ansatz auch etwas stört, ist die "Asymmetrie" zwischen der Schleife und dem "If empty"-Fall. If finde, wie bei `if/else` sollten idealerweise beide in der gleichen Form definiert werden. (Ich möchte nicht den `if`-Fall inline schreiben und den `else`-Fall als Funktion übergeben.) Vermutlich war das der Grund, warum ich die Übergabe des Schleifenrumpfs als Funktion ins Spiel gebracht hatte. Dann hätte man def my_loop_body(): ... def my_if_empty(): ... iter_if_not_empty(my_loop_body, my_if_empty) Aber natürlich ist das _noch mehr_ Schreibaufwand. Vielleicht habe ich noch etwas übersehen. Gibt es bessere Ansätze? Viele Grüße Stefan