Can I assign value to a variable among if condition on Python - python

I write my code that way, I want to assign matched values to 'm'
but lst[1] may not including the pat I want.
if it does, so I'll keep do something about 'm'
eg: m.group(2).split() ....
if re.match(pat, lst[1]):
m=re.match(pat, lst[1])
But I don't want to repeat the re.match(pat, lst[1]) twice.
I want to achieve in that way
if m = re.match(pat, lst[i])
but it shows me "invalid syntax error.
any ideas?

Just assign the value beforehand and check if it's None:
m = re.match(pat,lst[1])
if not m:
del m

You can abuse for for your task.
def for_if(expression):
if expression:
yield expression
for m in for_if(re.match(pat, lst[1])):
# work with m
or just
for m in (i for i in (re.match(pat, lst[1]),) if i):
# do the same
This is not really helpful for readability, but is the only way to combine assignment and test.

Related

Not able to add "/" in output

Create a function based on the input and output. Look at the examples, there is a pattern.
My code:
def secret(a):
b=a[:-2]
a_list=list(a)
last_number=int(a_list[-1])
Final_recurr=last_number+last_number
d="{} ".format(b)*Final_recurr
j=d.split()
for i,k in enumerate(j):
if int(i)%2!=0:
m="{}".format("</" + b+ ">")*Final_recurr
return m
if int(i)%2==0:
m="{}".format("<" + b+ ">")*Final_recurr
return m
I am not able to put / in every second iteration. Please tell me the mistake in current code and short version of this.
You can use str.split or str.partition to split the string into separate parts:
>>> "div*2".partition("*")
('div', '*', '2')
>>> tag_name, _, mult = "div*2".partition("*")
>>> tag_name
'div'
>>> mult
'2'
Use string formatting to insert tag_name into a template:
>>> "<{}></{}>".format(tag_name, tag_name)
'<div></div>'
"multiply" the formatted string with int(mult):
>>> "<{}></{}>".format(tag_name, tag_name) * int(mult)
'<div></div><div></div>'
>>>
You probably should familiarize more with programming basics before trying to solve challenges.
In this case, you have to understand that a return statement inside a function just exits the function even if it is in a loop.
Thus, at the first iteration of your for i, k in enumerate(j): loop, the code passes in the second condition and exits the function when it reaches the return statement.
So there is never a second loop and your loop is just inoperant.
Just fixing this problem won't be sufficient to get a working solution. I would advice to clarify in your head the steps needed to achieve what your want and even write them in the form of comments in an empty function (you could take steps suggested by #Qwerty in comment):
def secret(expression):
# split the argument into the bits before and after *
# combine the required string
# return the resulting string
Then try to address each comment, one at a time. Other responses should help you a lot in doing this.
Here are some links to the documentation of functions and concepts that could help you:
str.split
str.format
unpacking
This is the function that can help you, try it out:
s = 'div*2'
>>> def secret(s):
tag, n = s.split('*') # parse it into two parts
ans = f'<{tag}></{tag}>' # get complementary part
return ans * int(n) # final result
>>> secret(s)
'<div></div><div></div>'
>>> secret('p*1')
'<p></p>'
>>>

Error when trying to build logical parser

So i have these strings stored in database and i want to convert them to python expression to use them with if statement. I will store these strings into list and will loop over them.
For example:
string = "#apple and #banana or #grapes"
i am able to convert this string by replacing # with "a==" and # with "b==" to this :
if a == apple and b == banana or b == grapes
hash refers to a
# refers to b
But when i use eval it throws up error "apple is not defined" because apple is not in quotes. so what i want is this:
if a == "apple" and b == "banana" or b == "grapes"
Is there any way i can do this ?
The strings stored in DB can have any type of format, can have multiple and/or conditions.
Few examples:
string[0] = "#apple and #banana or #grapes"
string[1] = "#apple or #banana and #grapes"
string[2] = "#apple and #banana and #grapes"
There will be else condition where no condition is fullfilled
Thanks
If I understand correctly you are trying so setup something of a logical parser - you want to evaluate if the expression can possibly be true, or not.
#word or #otherword
is always true since it's possible to satisfy this with #=word for example, but
#word and #otherword
is not since it is impossible to satisfy this. The way you were going is using Python's builtin interpreter, but you seem to "make up" variables a and b, which do not exist. Just to give you a starter for such a parser, here is one bad implementation:
from itertools import product
def test(string):
var_dict = {}
word_dict = {}
cur_var = ord('a')
expression = []
for i,w in enumerate(string.split()):
if not i%2:
if w[0] not in var_dict:
var_dict[w[0]] = chr(cur_var)
word_dict[var_dict[w[0]]] = []
cur_var += 1
word_dict[var_dict[w[0]]].append(w[1:])
expression.append('{}=="{}"'.format(var_dict[w[0]],w[1:]))
else: expression.append(w)
expression = ' '.join(expression)
result = {}
for combination in product(
*([(v,w) for w in word_dict[v]] for v in word_dict)):
exec(';'.join('{}="{}"'.format(v,w) for v,w in combination)+';value='+expression,globals(),result)
if result['value']: return True
return False
Beyond not checking if the string is valid, this is not great, but a place to start grasping what you're after.
What this does is create your expression in the first loop, while saving a hash mapping the first characters of words (w[0]) to variables named from a to z (if you want more you need to do better than cur_var+=1). It also maps each such variable to all the words it was assigned to in the original expression (word_dict).
The second loop runs a pretty bad algorithm - product will give all the possible paring of variable and matching word, and I iterate each combination and assign our fake variables the words in an exec command. There are plenty of reasons to avoid exec, but this is easiest for setting the variables. If I found a combination that satisfies the expression, I return True, otherwise False. You cannot use eval if you want to assign stuff (or for if,for,while etc.).
Not this can drastically be improved on by writing your own logical parser to read the string, though it will probably be longer.
#Evaluted as (#apple and #banana) or #grapes) by Python - only #=apple #=banana satisfies this.
>>> test("#apple and #banana or #grapes")
True
#Evaluted as #apple or (#banana and #grapes) by Python - all combinations satisfy this as # does not matter.
>>> test("#apple or #banana and #grapes")
True
#demands both #=banana and #=grapes - impossible.
>>> test("#apple and #banana and #grapes")
False
I am not sure of what you are asking here, but you can use the replace and split functions :
string = "#apple and #banana"
fruits = string.replace("#", "").split("and")
if a == fruits[0] and b == fruits[1]:
Hope this helps

Reversing string in python using def

Can anyone help me with the assignment - I have to reverse a string by using def. I am not allowed to use approaches like [::-1] or .reversed...
The following function works, but prints vertically:
def ex1(name):
for x in range(len(name)-1,-1,-1):
print(name[x])
k
r
o
Y
w
e
N
how do I put the letters back into horizontal order?? Anyone? Thanks!
You can use str.join and a list comprehension like so:
>>> def ex1(name):
... return "".join([name[x] for x in range(len(name)-1,-1,-1)])
...
>>> print(ex1('abcd'))
dcba
>>>
Also, notice that I made the function return the string instead of print it. If your teachers want you to use def for this job, then they probably want that too. If not, then you can always replace return with print if you want.
You were very close:
def ex1(name):
reverseName=""
for x in range(len(name)-1,-1,-1):
reverseName+=name[x]
print reverseName
The print statement prints a newline character (a line break) after each line, this is why you get your characters in vertical. The solution is not to print the character in each loop, but to collect them in a string and print the final string at once at the end.
Note that there are more efficient ways of doing this (see the other answers), but it might be the most straightforward way and the closest one to what you have already done.
Here is another way that you can reverse a string.
def ex1(name):
length = len(name)
return "".join([name[length-x-1] for x in range(0, length)])
print ex1("hello world")
name=input("Whats your name ?")
def reversemyname(name):
x=name[::-1]
return x
reversedname=reversemyname(name)
print(reversedname)
print(name[x]), # <= add that comma
if you want the output like this kroy wen then try this:
sys.stdout.write(name[x])
remember to import sys

Python: Create dynamic loop based on pattern

I'm still learning to code in Python
I want to generate a string based on pattern, the only way I know is by using for loop.
In example code below, I create a loop for "vcvcv" pattern. c=consonant, v=vowel
How to create a dynamic loop, based on pattern that I provide to the script?
eg. if pattern is "cvcvc" the loop should be build to produce the string
Help appeciated.
Thanks.
#!/bin/env python
vowel="aeiou"
consonant="bcdfghjklmnpqrstvwxyz"
lvowel=list(vowel)
lconsonant=list(consonant)
# pattern for "vcvcv" = ababa
for a in lvowel:
for b in lconsonant:
for c in lvowel:
for d in lconsonant:
for e in lvowel:
myname=a+b+c+d+e
print myname
# pattern for "cvcvc" = babab
# how to make the loop dynamic based on pattern ?
Something like this should work:
import itertools
mapping = {
'v': 'aeiou',
'c': 'bcdfghjklmnpqrstvwxyz'
}
pattern = 'vcvcv'
for thing in itertools.product(*map(mapping.get, pattern)):
print ''.join(thing)
Here's roughly how it works:
map(mapping.get, pattern) just converts 'vcv' to ['aeiou', 'bcdfghjklmnpqrstvwxyz', 'aeiou']. It replaces each letter with the corresponding list of characters.
*map(...) unpacks the argument list.
itertools.product() is like a bunch of nested for loops.
''.join(thing) joins the list of characters into a single string.
If you want to do this without itertools, you'll have to make a recursive function.
If you're just getting into programming and want to see a more general solution than the itertools one listed above, then recursion is your best bet, allowing you to arbitrarily nest loops.
There is a slight complication here, which you could use Python generators for, or else use simpler (but messier) constructs. An example of the latter is shown below.
Something like
def continuePattern(pat, strSoFar):
if pat == '':
print strSoFar
elif pat[0] == 'v':
for c in lvowel:
continuePattern(pat[1:], strSoFar + c)
elif pat[0] == 'c':
for c in lconsonant:
continuePattern(pat[1:], strSoFar + c)
This is one of several possible implementations, and one of the two most naive ones I can imagine.
A somewhat more elaborate but easily customizable version for the first n permutations is given below,
def gen_pattern( seq, op = "" ):
vowel="aeiou"
consonant="bcdfghjklmnpqrstvwxyz"
lvowel=list(vowel)
lconsonant=list(consonant)
if ( not seq ):
print op
return
if ( seq[0] == 'v' ):
for v in lvowel:
gen_pattern( seq[1:], op+v )
elif ( seq[0] == 'c' ):
for c in lconsonant:
gen_pattern( seq[1:],op+c )
if __name__ == "__main__":
gen_pattern("vcvcv")
I agree it is more work though!

Do I have to cause an ValueError in Python

I have this code:
chars = #some list
try:
indx = chars.index(chars)
except ValueError:
#doSomething
else:
#doSomethingElse
I want to be able to do this because I don't like knowfully causing Exceptions:
chars = #some list
indx = chars.index(chars)
if indx == -1:
#doSomething
else:
#doSomethingElse
Is there a way I can do this?
Note that the latter approach is going against the generally accepted "pythonic" philosophy of EAFP, or "It is Easier to Ask for Forgiveness than Permission.", while the former follows it.
if element in mylist:
index = mylist.index(element)
# ... do something
else:
# ... do something else
For the specific case where your list is a sequence of single-character strings you can get what you want by changing the list to be searched to a string in advance (eg. ''.join(chars)).
You can then use the .find() method, which does work as you want. However, there's no corresponding method for lists or tuples.
Another possible option is to use a dictionary instead. eg.
d = dict((x, loc) for (loc,x) in enumerate(chars))
...
index = d.get(chars_to_find, -1) # Second argument is default if not found.
This may also perform better if you're doing a lot of searches on the list. If it's just a single search on a throwaway list though, its not worth doing.

Categories