5

このようなことがPythonで可能かどうか疑問に思っています(3.2、それが関連している場合)。

with assign_match('(abc)(def)', 'abcdef') as (a, b):
    print(a, b)

動作は次のとおりです。

  • 正規表現が一致する場合、正規表現グループはに割り当てられab
    • そこに不一致がある場合は、例外がスローされます
  • 一致する場合はNone、コンテキストを完全にバイパスします

ここでの私の目標は、基本的に、状況に応じた動作を行うための非常に簡潔な方法です。

次のコンテキストマネージャーを作成してみました。

import re

class assign_match(object):
    def __init__(self, regex, string):
        self.regex = regex
        self.string = string
    def __enter__(self):
        result = re.match(self.regex, self.string)
        if result is None:
            raise ValueError
        else:
            return result.groups()
    def __exit__(self, type, value, traceback):
        print(self, type, value, traceback) #testing purposes. not doing anything here.

with assign_match('(abc)(def)', 'abcdef') as (a, b):
    print(a, b) #prints abc def
with assign_match('(abc)g', 'abcdef') as (a, b): #raises ValueError
    print(a, b)

実際には、正規表現が一致する場合とまったく同じように機能しますが、ご覧のとおり、一致するものがValueErrorない場合はをスローします。終了シーケンスに「ジャンプ」する方法はありますか?

ありがとう!!

4

1 に答える 1

4

ああ!おそらく、SOでそれを説明することで、私にとって問題が明らかになりました。withステートメントの代わりにifステートメントを使用します。

def assign_match(regex, string):
    match = re.match(regex, string)
    if match is None:
        raise StopIteration
    else:
        yield match.groups()

for a in assign_match('(abc)(def)', 'abcdef'):
    print(a)

私が望む振る舞いを正確に与えます。他の人がそれから利益を得たい場合に備えて、これをここに残しておきます。(Mods、関連性がない場合は、削除してくださいなど)

編集:実際、このソリューションにはかなり大きな欠陥が1つあります。私はforループ内でこの動作を行っています。したがって、これは私が行うことを妨げます:

for string in lots_of_strings:
    for a in assign_match('(abc)(def)', string):
        do_my_work()
        continue # breaks out of this for loop instead of the parent
    other_work() # behavior i want to skip if the match is successful

これは、continueが、親のforループではなく、このループから抜け出すためです。誰か提案があれば、聞いてみたいです!

EDIT2:わかりました、今回は実際にそれを理解しました。

from contextlib import contextmanager
import re

@contextmanager
def assign_match(regex, string):
    match = re.match(regex, string)
    if match:
        yield match.groups()

for i in range(3):
    with assign_match('(abc)(def)', 'abcdef') as a:
#    for a in assign_match('(abc)(def)', 'abcdef'):
        print(a)
        continue
    print(i)

投稿してすみません-投稿する前に本当に行き詰まっていたことを誓います。:-)うまくいけば、他の誰かがこれを面白いと思うでしょう!

于 2012-05-26T19:09:03.710 に答える