I'm wondering if something like this is possible in python (3.2, if that's relevant).
with assign_match('(abc)(def)', 'abcdef') as (a, b):
print(a, b)
Where the behavior is:
a
and b
None
, it would just bypass the context entirelyMy goal here is basically an extremely concise way of doing the contextual behavior.
I tried making the following context manager:
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)
It actually works exactly as desired for the case when the regexes match, but, as you can see, it throws the ValueError
if there's no match. Is there any way I can get it to "jump" to the exit sequence?
Thanks!!
Ah! Perhaps explaining it on SO clarified the problem for me. I just use an if statement instead of a with statement.
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)
Gives exactly the behavior I'd like. Leaving this here in case other people want to benefit from it. (Mods, if it's not relevant, feel free to delete, etc.)
EDIT: Actually, this solution comes with one fairly large flaw. I'm doing this behavior within a for-loop. So this prevents me from doing:
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
Because the continue now breaks out of this loop instead of the parent for loop. If anyone has suggestions, I'd love to hear!
EDIT2: Alright, figured it out for real this time.
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)
Sorry for the post - I swear I was feeling really stuck before I posted. :-) Hopefully someone else will find this interesting!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With