Make sure that there are two values in a Dictionaries Key Python - python

I have a simple dictionary. I am able to check if one value is true. My problem arises when I need to check if two are correct. I want it to return false if one of the two are correct. But it returs True in this case
mydict = {}
mydict['Car'] = ['Diesel','Hatchback','2,ltr']
mydict['Bri'] = ['Hatchback','2ltr']
print(mydict.get('Car'))
if 'Diesel' in mydict.get('Car'):
print('Found')
else:
print('This is false')
if 'Diesel' and 'Hatchback' in mydict.get('Bri'):# Here it needs these two values to be true.
print('Found')
else:
print('This is false')

This is not being evaluated the way you think it is:
'Diesel' and 'Hatchback' in mydict.get('Bri')
But like this
'Diesel' and ('Hatchback' in mydict.get('Bri'))
So 'Diesel' evaluates to True and the second part too.
What you want is something like this:
data = mydict.get('Bri')
if 'Diesel' in data and 'Hatchback' in data:
...
PS: Although this question might be a duplicate of this one as marked above, the answers there are way more complex than needed for this simple case

Related

If sentence with a text condition in python

I need to write an if loop in pyhon. My condition is related to a text (dict_keys). in particular, i have:
condition = f.get_best().keys()
When i read the condition element, it returns:
dict_keys(['laplace'])
Where i can have 'laplace' or 'gumbel'.
My goal is to perform different calculation if laplace or gumbel is returned.
My attempt so far:
condition = f.get_best().keys()
if condition == dict_keys(['laplace']):
print('Laplace case')
elif condition == dict_keys(['gumbel']):
print('gumbel case')
But it doesn't work. i also tried with:
if condition == laplace:
if condition == 'laplace':
But none of these seem to work. How can i do it?
dict_keys can't be used explicitly, it's internal of a dictionary. Use the following instead:
best_keys = f.get_best().keys()
if 'laplace' in best_keys:
print('Laplace case')
elif 'gumbel' in best_keys:
print('gumbel case')
You can change condition to a list and then compare the list with what you want it to be.
Would be done like this.
if list(condition) == ['laplace']:
(if the dictionary has multiple keys you should use in).
One could use match. This makes addition of new cases fairly easy.
>>> def lagumbl(cnd):
... match cnd:
... case "laplace":
... print(f["laplace"])
... case "gumbel":
... print(f["gumbel"])
...
>>> for cond in f.get_best().keys():
... lagumbl(cnd=cond)
...
laplace here
gumbel here

Python if statement always returns false, even though input is true

So I'm writing a program (A sort of "custom if statement") that checks if your input is true or false. This is the script I have right now:
v=line[3:] # Remove "if " from the line, so you only have the question and the consequence
i=v.split(': ') # Make a list with the first item being the question and the second item being the consequence.
for r in i:
if r==i[1]: # Check which item in the list is the question and which is the consequence
c=r
question=i[0]
consequences=c.split(' | ')
for x in consequences:
self.consequences+=f'\n{x}' # Create a variable with all of the consequences, each in one line
Answer=False # reate the Answer variable with the default value False
def checkVal(question):
global Answer
if question:
b=open('if.BaRT','w+')
b.write(self.consequences)
b.close()
self.run('if.BaRT')
os.remove('if.BaRT')
else:
pass # Check if the question is true or false
if Answer==True:
print("True!")
else:
print("False!") # Finally check if the question is true or not and if it is, print "True!" and if it's not, print "False!"
I'm expecting this to work, but then when i input something that's true, for example: __name__=="__main__", so my input looks like this:
if __name__=="__main__": print("Hello!")
this is the output:
False!
How do I fix this so it prints it accurately?
Edit: consequences added
I have replaced your exec with eval to get rid of your global variable (still not good coding practise, but if this is what you need...). Also, the for is not needed.
PS: the variables i, v and c should have better names.
line='if __name__=="__main__": print("Hello!")'
v=line[3:] # Remove "if " from the line, so you only have the question and the consequence
i=v.split(': ') # Make a list with the first item being the question and the second item being the consequence.
c=i[1]
question=i[0]
consequences=c.split(' | ')
_consequences=''
for x in consequences:
_consequences+=f'\n{x}'
Answer=eval(f"{question}") # Check if the question is true or false
if Answer==True:
exec( _consequences)
print("True!")
else:
print("False!") # Finally check if the question is true or not and if it is, print "True!" and if it's not, print "False!"

Is there a way to achieve a sort of placeholder for Python object attributes?

Hoping someone can help me with just pseudocode. I can't copy the code here as it's not entirely my own.
I have a function that looks like this:
for result in results_set:
if conditionA:
# When conditionA is true, test on this_attribute.
if result.this_attribute == "interesting string":
# do things.
if result.this_attribute == "another interesting string"
# do different things.
else:
# ConditionA is false? Test on that_other_attribute instead.
if result.that_other_attribute == "interesting string"
# do the same exact things as above for "interesting string"
if result.that_other_attribute == "another interesting string"
# do the same exact things as above for "another interesting string"
It seems very inefficient to have the test for conditionA or conditionB be inside the for loop since I deal with results_sets that can be thousands of lines long. Plus the code looks bad because I'm just repeating myself.
Feels like I should be able to test for conditionA / B before the loop takes place, and tell Python what attribute of "result" to compare next based on that test.
Which attribute I test will always depend on the value of ConditionA. I may end up with a ConditionB, C or D in the near future as well which will require checking on a third, fourth or fifth attribute of result.
Currently I solved this by having two nearly identical functions that each have their own "for" without the ConditionA test inside it... but that looks bad and will become a nightmare when B, C or D roll around.
Is it possible to have an attribute placeholder somehow? If so, how please?
Edit:
I am trying to achieve something like this....
result = a filler value used only to reference attribute names
if ConditionA:
check_attribute = result.this_attribute
else:
check_attribute = result.that_other_attribute
for result in results_set:
if check_attribute == "interesting string":
# do things.
if check_attribute == "another interesting string"
# do different things.
Using getattrs might get you somewhere here, however unlikely that may sound. Right above the for loop, you could do
value_to_check = "this_attribute" if conditionA else "that_other_attribute".
Yes, those were strings.
Next, in the for loop, you could do
result_value = getattr (result, value_to_check)
if result_value == "interesting string": #thing to do
elif result_value == "another interesting string": #other thing to do

Working on basic recursion- trying to recursively look through a string for two characters

I'm super new to python, and trying to create a very simple function to be used in a larger map coloring program.
The idea of the function is to have a set of variables attributed to different regions (string1) with colors assigned to them, (r,g,b) and then test if the regions touch another region of the same color by recursively looking through a set of region borders (string2) to find variables+colors that match.
The input format would look like this:
("Ar, Bg, Cb", "AB,CB,CA")
Would return True, meaning no two regions of the same color touch.
Here's my code segment so far:
def finding_double_char_function(string1, string2):
if string2=="":
return True
elif string2[0]+"r" and string2[1]+"r" in string1 or string1[::-1]:
return False
elif string2[0]+"g" and string2[1]+"g" in string1 or string1[::-1]:
return False
elif string2[0]+"b" and string2[1]+"b" in string1 or string1[::-1]:
return False
else:
return finding_double_char_function(string1, (string2[3:]))
I keep getting false when I expected True. Can anyone help? Thanks a lot.
You have several problems in this, but your main problem is that you don't seem to know the order of bindings in an expression. What you've written is a little more readable like this:
elif string2[0]+"r" and
((string2[1]+"r" in string1) or
string1[::-1]) :
In other words, you've used strings as boolean values. The value you get from this is not what you expected. I think what you're trying to do is to see whether either constructed string (such as "Ar") is in string 1, either forward or backward.
"in" can join only one pair of strings; there's no distributive property of "and" and "or" over "in".
Here's the first part rewritten properly:
elif (string2[0]+"r" in string1) and
(string2[1]+"r" in string1)
Does this get you going?
Also, stick in print statements to trace your execution and print out useful values along the way.
If I undestood correctly your problem could be solved like this:
def intersect(str1, str2):
if (not str2):
return True
if (str1[str1.find(str2[0]) + 1] == str1[str1.find(str2[1]) + 1]):
return False
else:
return intersect(str1, str2[3:])

how to loop over each changeInfo['changeInfo'][1...x]['Url']

I have the following code snippet ,i want to change it in such a way where I want loop over for each changeInfo['changeInfo'][1..x],how can I do that
for changeInfo in MainchangeInfo:
if (changeInfo['CRStatus'] == 'Fix' and (('Not Provided' in changeInfo['changeInfo'][0]['Url'] or 'Wrong change Provided' in changeInfo['changeInfo'][0]['Url']) or 'NEW' in changeInfo['changeInfo'][0]['Status'] or 'ABANDONED' in changeInfo['changeInfo'][0]['Status'] or 'Yes' not in changeInfo['RNotesStatus'] or 'Provided' not in changeInfo['RCAInfo'] or 'False' in str(changeInfo['IsDevComplete']))):
if 'Wrong change Provided' in changeInfo['changeInfo'][0]['Url'] or changeInfo['changeInfo'][0]['Info'] != 'Available' ://want to loop over for changeInfo['changeInfo'][0]
changeMailBody = changeMailBody + "<tr bgcolor=\"Red\">"
what do you mean by [1..x]?
if you want to loop over the 'first x' elements in changeInfo['changeInfo'] (in which case, did you mean [0..x]?) you can use slice notation:
for item in changeInfo['changeInfo'][:x]:
# do stuff
if you really want from 1 to x, i.e. skipping the first element you can do:
for item in changeInfo['changeInfo'][1:x]:
# do stuff
See docs here:
http://docs.python.org/2.3/whatsnew/section-slices.html
EDIT:
After your clarification in the comment it's clear you don't even need slice notation, you just need for item in changeInfo['changeInfo'] ...I think your full example would look like:
for changeInfo in MainchangeInfo:
for item in changeInfo['changeInfo']:
if (changeInfo['CRStatus'] == 'Fix' and (('Not Provided' in item['Url'] or 'Wrong change Provided' in item['Url']) or 'NEW' in item['Status'] or 'ABANDONED' in item['Status'] or 'Yes' not in changeInfo['RNotesStatus'] or 'Provided' not in changeInfo['RCAInfo'] or 'False' in str(changeInfo['IsDevComplete']))):
if 'Wrong change Provided' in item['Url'] or item['Info'] != 'Available' ://want to loop over for changeInfo['changeInfo'][0]
changeMailBody = changeMailBody + "<tr bgcolor=\"Red\">"
You can do this with an explicit loop:
for change in changeInfo['changeInfo']:
info = change['info']
# do stuff with it
Or, if you want to write it out as a comprehension:
infos = [change['info'] for change in changeInfo['changeInfo']]
Or, if you just want an iterator, not a list:
infos = (change['info'] for change in changeInfo['changeInfo'])
In any case, you will get changeInfo['changeInfo'][0]['info'], then changeInfo['changeInfo'][1]['info'], and so on.
I'm assuming here that changeInfo['changeInfo'] is a list, not a dict whose keys happen to be small integers. If that assumption is wrong, just replace changeInfo['changeInfo'] with changeInfo['changeInfo'].values() in whichever solution you choose. (Of course in that case, the order will be arbitrary, but that's exactly what you should expect from a dict.)
So, in your existing code, instead of this:
if ('Wrong change Provided' in changeInfo['changeInfo'][0]['Url'] or
changeInfo['changeInfo'][0]['Info'] != 'Available'):
… I'd use the generator expression, together with the any function, like this:
if any('Wrong change Provided' in change['Url'] or change['Info'] != 'Available'
for change in changeInfo['changeInfo']):
Now instead of checking whether this condition is true for the first value in changeInfo['changeInfo']—that is, changeInfo['changeInfo'][0]—you're testing whether it's true for any of the values in changeInfo['changeInfo']. Which, as I understand it, is exactly what you wanted.

Categories