0

I need to find a way to call a way to use something with fstring syntax to retrieve information from a string.

My goal is to use the same fstring to create a string, and then decode it.

For example:

def encode():
    a = "fizz"
    b = "buzz"
    return f"{a} / {b}"

def decode(my_string: str):
    a = ""
    b = ""
    f"{a} / {b}" # Something like that, more or less.
    print(a) # fizz
    print(b) # buzz

I know this example is stupid, but I really need something like that. I work with a proprietary testing software that allow me to call python script, but these scripts can only return values to the software by writing to stdout. And, then, I want to retrieve them in another script called further.


I know there is a possibility to retrieve it with regex, but I want to have the same "fstring" for both functions, to avoid duplication.

Apitronix
  • 305
  • 2
  • 13
  • 1
    From the output of `encode` you have no information about which parts of the string were formatted to begin with. If you had the _template_ (`"{a} / {b}"`), which was then used with `str.format`, you might have more success. – jonrsharpe Feb 03 '22 at 11:38
  • 2
    Yes if you have a template then you would use [python-parse](https://pypi.org/project/parse/). – wim Feb 03 '22 at 11:40
  • @wim that's a very handy library, although I'd have been tempted to call it `gstring`... – Ari Cooper-Davis Feb 03 '22 at 11:41
  • 1
    A general approach is impossible, because `a` and `b` might contain the substring `" / "` themselves so the result would be ambiguous. There are several approaches for this specific case where `a` and `b` are more constrained, such as `split` and `re`. – Thomas Feb 03 '22 at 11:51
  • Formatting and parsing are so different, that "having the same fstring to avoid duplication" does not give any advantage. – VPfB Feb 03 '22 at 11:52
  • Sounds like possible [XY Problem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). *Why* exactly do you "really need something like that"? Regardless, I would say "no" because there is a loss of information involved. – martineau Feb 03 '22 at 12:46

4 Answers4

1
def encode():
    a = "fizz"
    b = "buzz"
    return f"{a}/{b}"

def decode(my_string: str,d="/"):
    a,b = my_string.split(d)
    print(a) # fizz
    print(b) # buzz

tomerar
  • 805
  • 5
  • 10
1

To a certain degree this is possible if you can make restrictions to your arguments a and b and your string. E.g. if your string always has the form f"{a} / {b}" and no " / " appears in a or b you can use that information:

def encode(a, b):
    return f"{a} / {b}"

def decode(my_str: str):
    return my_str.split(" / ")


a = "fizz"
b = "buzz"

my_str = encode(a, b)
dec_a, dec_b = decode(my_str)
print(dec_a, dec_b)
mapf
  • 1,906
  • 1
  • 14
  • 40
0

You should split using your delimiter, in this case it was "/". So do the following:

def decode(myString: str, delimiter="/"):
    a,b = muString.split(delimiter)
    print(f"{a}/{b}")
  • The main drawback of your answer is that if I change the parameters order in "encode" function, then I need to change them in "decode" too. – Apitronix Feb 03 '22 at 12:43
0

You can, to some extent, turn it on its head and have a "reverse regular expression". It works by parsing the regular expression with another regular expression (yikes!):

import re

pattern = r'(?P<a>.*?) / (?P<b>.*?)'

def format_re(regexp, **kwargs):
    def replace_fn(match):
        return kwargs[match.group('group_name')]
    return re.sub(
        r'\(\?P<(?P<group_name>.*?)>.*?\)',
        replace_fn,
        pattern)

def encode(a, b):
    return format_re(pattern, a=a, b=b)

def decode(my_string):
    match = re.match('^' + pattern + '$', my_string)
    return match.group('a'), match.group('b')

print(encode('fizz', 'buzz')) # fizz / buzz
print(decode('fizz / buzz'))  # ('fizz', 'buzz')

Of course, unnamed, nested and repeated groups will cause trouble, and so will regex metacharacters outside capture groups. And I'm sure there are other problems with it that I don't care to think about right now.

I don't think all this overhead is better than the very slight amount of duplication, but there you have it.

Thomas
  • 174,939
  • 50
  • 355
  • 478