Nesting / escaping a f-string "=" (equal sign) expression - python

Is it possible to escape a python f-string within a "=" expression? (new feature in Python 3.8)
For example I have the following expression:
def double(x):
return x * 2
some_int = 2
print(f'{double(some_int) = }')
Which prints:
double(some_int) = 4
Is it possible to escape the some_int parameter in a way so that it prints:
double(2) = 4
Or do I have to type the expression twice and concatenate the literal expression and result the old-fashioned way?

As said in the What's New In Python 3.8 document:
Added an = specifier to f-strings. An f-string such as f'{expr=}' will
expand to the text of the expression, an equal sign, then the
representation of the evaluated expression.
So no, you can't do it that way(one shot) because the left side of = will become a string. Use traditional f-string interpolation:
print(f'double({some_int}) = {double(some_int)}')
Output:
double(2) = 4

Your code did not run, however I assume you mean to do:
some_int = 2
print(f'double({some_int}) = {some_int*2}')
which prints:
double(2) = 4

Related

RegEx pattern written as f-string returns different result than a raw string one [duplicate]

This question already has answers here:
How do I escape curly-brace ({}) characters in a string while using .format (or an f-string)?
(23 answers)
Closed 2 years ago.
I'm trying to match this:
text = "111111"
reps = 2
f_pattern = re.compile(rf"(\w)(?=\1{{reps}})")
f_matches = re.findall(f_pattern, text)
## returns: []
r_pattern = re.compile(r"(\w)(?=\1{2})")
r_matches = re.findall(r_pattern, text)
## returns: ['1', '1', '1', '1']
How should the f-string pattern be written to return non-empty result?
Write rf"(\w)(?=\1{{{reps}}})") instead of rf"(\w)(?=\1{{reps}})").
{{ is a way to escape single { inside any f-string, same for }.
Try it online!
As mentioned in this answer:
How do I use format() in re.compile
Double braces are interpreted as literal braces in format strings. You need another, third set, to indicate that len is a formatted expression.
If you use double brace, f-string thinks its a literal brace and skips it. use 3 braces so 2 of the braces will be considered as a literal brace and another set for format string.
You need to double the curly bracket for literal print. so here is the solution
text = "111111"
reps = 2
f_pattern = re.compile(rf"(\w)(?=\1{{ {reps} }})")
f_matches = re.findall(f_pattern, text)

In Python, how can you write the string String = "\s"? [duplicate]

This question already has answers here:
Why do backslashes appear twice?
(2 answers)
Closed 7 months ago.
Why does:
B = "The" + "\s"
and
B = "The" + r"\s"
yield:
"The\\s"
Is it possible to write the above, such that the output string is:
"The\s"
I have read similar questions on both the issue of backslashes, and their property for escaping, and the interpretation of regex characters in Python.
How to print backslash with Python?
Why can't Python's raw string literals end with a single backslash?
Does this mean there is no way to write what I want?
If it is useful, My end goal is to a write a program that adds the regex expression for space (\s) to a string where this such space:
For example, start with:
A = "The Cat and Dog"
After applying the function, this becomes:
B = "The\sCat\sand\sDog"
I believe this is related to Why does printing a tuple (list, dict, etc.) in Python double the backslashes?
The representation of the string and what it actually contains can differ.
Observe:
>>> B = "The" + "\s"
>>> B
'The\\s'
>>> print B
The\s
Furthermore
>>> A = "The Cat and Dog"
>>> B = str.replace(A, ' ', '\s')
>>> B
'The\\sCat\\sand\\sDog'
>>> print B
The\sCat\sand\sDog
From the docs:
all unrecognized escape sequences are left in the string unchanged, i.e., the backslash is left in the result
So while \s is not a proper escape sequence, Python forgives you your mistake and treats the backslash as if you had properly escaped it as \\. But when you then view the string's representation, it shows the backslash properly escaped. That said, the string only contains one backslash. It's only the representation that shows it as an escape sequence with two.
You must escape the "\"
B = "The" + "\\s"
>>> B = "The" + "\\s"
>>> print(B)
The\s
See the Escape Sequences part:
Python 3 - Lexical Analysis

Python: Solving math in string using regex

I am using regex to solve basic math in strings, like '1+(-5)^2'. I want to use regex to find the number before ^ (base, in this case (-5)) and the number after ^ (exponent, in this case 2) and then replace (-5)^2 with base ** exponent (25 in this case). The numbers are real, I used integers in the example to make it more clear.
The string can be any mathematical expression, and the exponential part can be in any of these forms:
>>> (-5)^(-2)
('(-5)', '(-2)')
>>> (-5)^2
('(-5)', '2')
>>> 5^(-2)
('5', '(-2)')
>>> 5^2
('5', '2')
>>> -5^2
('5', '2')
Even forms where the brackets are redundant, like:
>>> (5)^(+2)
('(5)', '(+2)')
I tried this:
import re
a = '1+(-5)^2'
while True:
exp = re.search('((?:\([\+\-]?\d+(?:\.\d+)?\)|\d+(?:\.\d+)?))\^((?:\([\+\-]?\d+(?:\.\d+)?\)|\d+(?:\.\d+)?))', a)
exp_list = list(exp.groups())
base = exp_list[0].replace('(', '')
base = base.replace(')', '')
exponent = exp_list[1].replace('(', '')
exponent = exponent.replace(')', '')
if exp:
temp = (float(base)) ** float(exponent)
a = re.sub('(\([\+\-]?\d+(?:\.\d+)\)|\d+(?:\.\d+)?)\^(\([\+\-]?\d+(?:\.\d+)?\)|\d+(?:\.\d+)?)', str(temp), a, count=1)
print a
if not exp:
break
I have two problems:
It never breaks out of the loop (I need the loop because there can be ^ more than once in the string)
It does not replace temp in the string a.
You can use pythons 'eval' function to evaluate these e.g.
expr = '3*5'
print eval(eval) # returns 15
I have two problems:
It never breaks out of the loop (I need the loop because there can be ^ more than once in the string)
It does not replace temp in the string a.
This is actually one and the same problem - since it loops until there is nothing more to replace, and it fails to replace what is there, it loops forever.
That it fails to replace what it should, comes from a small but crucial difference in the patterns you use in re.search() and re.sub() (blanks inserted for easier comparison):
((?:\([\+\-]?\d+(?:\.\d+)?\)|\d+(?:\.\d+)?))\^((?:\([\+\-]?\d+(?:\.\d+)?\)|\d+(?:\.\d+)?))
  ↕                                                                
( \([\+\-]?\d+(?:\.\d+) \)|\d+(?:\.\d+)?) \^( \([\+\-]?\d+(?:\.\d+)?\)|\d+(?:\.\d+)?) 
You omitted a quantifier ? in the latter pattern.
The moral of the story is to not use separate patterns when the same thing must be matched and replaced. Change:
pattern = \
'((?:\([\+\-]?\d+(?:\.\d+)?\)|\d+(?:\.\d+)?))\^((?:\([\+\-]?\d+(?:\.\d+)?\)|\d+(?:\.\d+)?))'
while True:
exp = re.search(pattern, a)
if not exp: break
…
a = re.sub(pattern, str(temp), a, 1)
That all said, of course hek2mgl is right noting: You can't use a regex for that. You'll need to write a parser for that.

using a variable whose value is an integer in a regular expression (python)

Suppose I have the following regular expression in Python and I would like to use a variable instead of [1-12]. For example, my variable is currentMonth = 9
How can I plug currentMonth into the regular expression?
r"(?P<speaker>[A-Za-z\s.]+): (?P<month>[1-12])"
Use string formating to insert currentMonth into the regex pattern:
r"(?P<speaker>[A-Za-z\s.]+): (?P<month>{m:d})".format(m=currentMonth)
By the way, (?P<month>[1-12]) probably does not do what you expect. The regex [1-12] matches 1 or 2 only. If you wanted to match one through twelve,
you'd need (?P<month>12|11|10|[1-9]).
I dont know what you're searching through so I can't test this but try:
(r"(?P<speaker>[A-Za-z\s.]+): (?P<month>%r)" % currentMonth, foo)
where foo is the string you're using the expression on.

Is it possible to use a back reference to specify the number of replications in a regular expression?

Is it possible to use a back reference to specify the number of replications in a regular expression?
foo= 'ADCKAL+2AG.+2AG.+2AG.+2AGGG+.G+3AGGa.'
The substrings that start with '+[0-9]' followed by '[A-z]{n}.' need to be replaced with simply '+' where the variable n is the digit from earlier in the substring. Can that n be back referenced? For example (doesn't work) '+([0-9])[A-z]{/1}.' is the pattern I want replaced with "+" (that last dot can be any character and represents a quality score) so that foo should come out to ADCKAL+++G.G+.
import re
foo = 'ADCKAL+2AG.+2AG.+2AG.+2AGGG+.+G+3AGGa.'
indelpatt = re.compile('\+([0-9])')
while indelpatt.search(foo):
indelsize=int(indelpatt.search(foo).group(1))
new_regex = '\+%s[ACGTNacgtn]{%s}.' % (indelsize,indelsize)
newpatt=re.compile(new_regex)
foo = newpatt.sub("+", foo)
I'm probably missing an easier way to parse the string.
No, you cannot use back-references as quantifiers. A workaround is to construct a regular expression that can handle each of the cases in an alternation.
import re
foo = 'ADCKAL+2AG.+2AG.+2AG.+2AGGG^+.+G+3AGGa4.'
pattern = '|'.join('\+%s[ACGTNacgtn]{%s}.' % (i, i) for i in range(1, 10))
regex = re.compile(pattern)
foo = regex.sub("+", foo)
print foo
Result:
ADCKAL++++G^+.+G+4.
Note also that your code contains an error that causes it to enter an infinite loop on the input you gave.

Categories