How should this test be understood, and should it be written differently? - python

Here is a piece of code where the length of v is either 0, 1 or 2, and can contain identical or different data and data types.
result = False
v = [3, 4] # just an example, could be v = [None, None] instead
try:
result |= v[0] == v[1] is not None # THIS IS THE TEST
except Exception:
pass
How should the line result |= v[0] == v[1] is not None be understood? Should it be written in another way (whatever it is supposed to be doing)?

First, to know what this test is doing, you need to know what |= means.
|=, is the same sort of shortcut as +=, this means that
a |= b
actually means
a = a | b
A common case for the operator | is for dictionnaries :
dict1 = {"a":10, "b":12}
dict2 = {"c":80, "d":37}
dict3 = dict1 | dict2
print(dict3)
Result :
{"a":10, "b":12, "c":80, "d":37}
This is a sort of "merge" operator, it merges an union with another union, or data with another data, to be simple.
Now that this is understood, we need to focus on the other part of the test :
v[0] == v[1] is not None
This test simply means
Does the condition v[0] == v[1] equals not None?
If it does equals to not None, returns True
In this case: v[0] = 3 and v[1] = 4
So, this condition is :
(3 == 4) is (not None)
False is (not None)
False isn't not None
So, this test returns False.
Now, the full test : result |= v[0] == v[1] is not None
What does it do ? It symply do :
Merge the variable result equals to the returned value of the test v[0] == v[1] is not None
As we know, this : v[0] == v[1] is not None returns False, so it simply says :
Merge the variable result with the returned value of v[0] == v[1] is not None
So :
Merge the variable result with False
False merged with False makes False. So,all of this simply makes the result variable being False.
This is why, when printing result, it prints False !
(Hope that helps)

Related

Find most elegant way to return key if condition is set to true

I have a python dictionary
slot_a = 'a'
slot_b = 'b'
# dict which lists all possible conditions
con_dict = {"branch_1": slot_a == 'a' and slot_b == 'b',
"branch_2": slot_a == 'a' and slot_b == 'c'}
Now I want to return the key for the first true condition. In this case it's branch_1.
My solution is:
# Pick only the condition which is set to True
true_branch = [k for k, v in con_dict.items() if v == True]
true_branch
>>> branch_1
Since the number of branches can be very long, I was wondering, if there might be a more elegant way to get the same result?! Maybe if / elif / else and then return key? Or even something completely different? All I need at the end is the name of the true condition. Therefore working with a dict may not even be necessary.
Just asking for inspiration!
You could try to use an iterator. It will stop as soon it gets the first match without going through the whole "object".
ks, vs = zip(*con_dict.items()) # decoupling the list of pairs
i = 0
vs = iter(vs) # terms are all booleans
while not next(vs):
i += 1
del vs # "free" the iterator
print(ks[i])
or
true_branch = next((k for k, condition in con_dict.items() if condition), None)
print(true_branch)

Recursion help - Peter Norvig's Sudoku exercise

Hi I am currently going through Peter Norvig's sudoku solution (http://norvig.com/sudoku.html).
However, I have a bit of confusion with the block code below:
def assign(values, s, d):
"""Eliminate all the other values (except d) from values[s] and propagate.
Return values, except return False if a contradiction is detected."""
other_values = values[s].replace(d, '')
if all(eliminate(values, s, d2) for d2 in other_values):
return values
else:
return False
def eliminate(values, s, d):
"""Eliminate d from values[s]; propagate when values or places <= 2.
Return values, except return False if a contradiction is detected."""
if d not in values[s]:
return values ## Already eliminated
values[s] = values[s].replace(d,'')
## (1) If a square s is reduced to one value d2, then eliminate d2 from the peers.
if len(values[s]) == 0:
return False ## Contradiction: removed last value
elif len(values[s]) == 1:
d2 = values[s]
if not all(eliminate(values, s2, d2) for s2 in peers[s]):
return False
## (2) If a unit u is reduced to only one place for a value d, then put it there.
for u in units[s]:
dplaces = [s for s in u if d in values[s]]
if len(dplaces) == 0:
return False ## Contradiction: no place for this value
elif len(dplaces) == 1:
# d can only be in one place in unit; assign it there
if not assign(values, dplaces[0], d):
return False
return values
The function assign receive an input of a dictionary values and will return values as well if there is no contradiction. However, in the assign function, I did not see any update on the dictionary values. My understanding is that dict values is updated with the eliminate function (and after running the code, I believe this is the case). However, this is done outside of the assign function and should not affect the values in the assign function, as it is not updated directly in the function.
Maybe you guys can give me a shed of light?
Python dicts are mutable, meaning that their value can be changed.
This example is showing an anti-pattern: You shouldn't both mutate an argument and return it. An example is all the methods that change a list (append, pop, etc.) don't return the original list.
The eliminate function gets the same dict as in the assign function, and any changes in the assign function are reflected in the elimate function.
Here is an example:
def update(dict_, key, value):
dict_[key] = value
d = {
1: 2,
3: 4
}
update(d, 1, 100)
update(d, 3, 100)
print(d[1] + d[3]) # 200

How to get the last occurrence of list as output?

Can anyone please explain how to output the rightmost index from several most-same-values indexes in the list?
my function:
def last_index(xs,key):
i = 0
for i in range(len(xs)):
if xs[i] == key:
if i != len(xs):
return i
else:
return 'None'
for example,
xs = [3,4,5,6,4,4,5]
key = 4
the rightmost index output should be a single 5. But I got all three all them which are index 1,4,5.
Thanks for the help, and sorry I'm totally new.
what if the input as strings like:
xs=[True,True,True,False]
key = True
I believe the output is 2?
This simple solution should do:
def last_index(xs, key):
index = None
for i in xrange(len(xs)):
if xs[i] == key:
index = i # override index, result in the rightmost index of key
return index # returns None if key is not on the list
A more efficient way to do this is by iterating from the end to start and returning the index when key is found, in worst case - key is not found and we will iterate over the entire list.
Check out the more efficient version:
def last_index(xs, key):
index = None
for i in xrange(len(xs)-1, 0, -1): # iterate from last item to first
if xs[i] == key:
index = i
break # found the rightmost index, exit the loop
return index
Notice you should prefer using xrange over range (unless in python 3 where range equals to xrange), also to avoid an edge case when items involve different types see Andriy's answer.
You can try a function like this
def last_index(xs,key):
index = -1
for i in range(len(xs)):
if xs[i] == key:
index=i
if index!=-1:
return index
else:
return "none"
This will get the last index that matches your key. If there is none will return "none".
This should do the trick:
def last_index(xs,key):
index = -1
for i in range(len(xs)):
if xs[i] != key:
continue
else:
index = i
return index if index != -1 else 'None'
Traverse xs in reverse order and return first matched value, with reversed function:
def last_index(xs,key):
for i in reversed(range(len(xs))):
if xs[i] == key:
return i
xs = [3,4,5,6,4,4,5]
key = 4
print last_index(xs, key) # output: 5
xs=[True,True,True,False]
key = True
print last_index(xs, key) # output: 2
print last_index(xs, 2) # output: None
NOTE#1
You can use xrange instead of range it would give you better performace and won't be deprecated since python3, see Should you always favor xrange() over range()? for more info.
Your comparison may be improved by replacing
if xs[i] == key
to
if xs[i] == key and type(a) == type(b)
NOTE#2
To avoid bug when your 1 == True would return you index of True however you wanna index of 1 whicn not exist, compare result for both if conditions when xs and key have values below
xs=[True,True,True,False]
key = 1
See Strict comparison for more information about that behaviour.
You can reverse the list and then use .index():
index = xs[len(xs) - list(reversed(xs)).index(key)]
By the way, in your second list, True and False are booleans, not strings.
Iterate from behind like this:
def last_index(xs,key):
i= len(xs)-1
while i >=0:
if xs[i] == key:
return i
i -= 1
This way if the key does not exist the function will return the none value

Difference between: IF IN and IF == python

I wanted to know which condition is better to use for the following code:
Here are my two lists:
Matrix = ['kys_q1a1','kys_q1a2','kys_q1a3','kys_q1a4','kys_q1a5','kys_q1a6']
fixedlist = ['kys_q1a2', 'kys_q1a5']
Option 1:
for i, topmember in enumerate(Matrix):
for fixedcol in fixedlist:
if topmember in fixedcol:
print i
OR
Option 2:
for i, topmember in enumerate(Matrix):
for fixedcol in fixedlist:
if topmember == fixedcol:
print i
I understand that the comparison opertor is matching strings but isn't 'in' doing the same?
Thanks
topmember in fixedcol
tests if the string topmember is contained within fixedcol.
topmember == fixedcol
tests if the string topmember is equal to fixedcol.
So, 'a' in 'ab' would evaluate True. But 'a' == 'ab' would evaluate False.
I wanted to know which condition is better to use.
Since the two variants perform different operations, we cannot answer that. You need to choose the option that does the operation that you require.
Your code could be simplified quite a bit. The second option could be reduced to:
for i, topmember in enumerate(Matrix):
if topmember in fixedlist:
print i
You could also use a list comprehension to find the matching indices:
[i for i, x in enumerate(Matrix) if x in fixedlist]
If you just have to print the indices rather than store them in a list you can write it like this:
print '\n'.join([str(i) for i, x in enumerate(Matrix) if x in fixedlist])
It's a matter of taste whether you prefer the dense list comprehension one-liner, or the rather more verbose version above.
Hi in opeartor is used for membership testing and == operator is used for equality testing .
Generally we used in for membership testing in sequence object. And is able to test in dictionary, set, tuple, list, string etc. But it behaves differently based on the object types.
Dictionary:
It check for the key exists.
>>> d = {'key' : 'value'}
>>> 'key' in d
True
>>> 'k' in d
False
>>>
Set:
Under the hood it checks for key is exist, set implementation is same as dictionary with some dummy value.
>>> s = set(range(10))
>>> 1 in s
True
>>>
List and Tuple:
For the list and tuple types, x in y is true if and only if there exists an index i such that x == y[i] is true.
>>> l = range(10)
>>> 3 in l
True
>>>
String:
checking whether the substring is present inside the string eg. x in y is true if and only if x is a substring of y. An equivalent test is y.find(x) != -1
Use defined data type:
user-defined classes which define the __contains__() method, x in y is true if and only if y.__contains__(x) is true.
class Person(object):
def __init__(self,name,age):
self.name = name
self.age = age
def __contains__(self, arg):
if arg in self.__dict__.keys():
return True
else:
return False
obj_p = Person('Jeff', 90)
print 'Jeff', 'Jeff' in obj_p
print 'age', 'age' in obj_p
print 'name', 'age' in obj_p
I Hope, you will clear some what is the usage of in.
Lets rewrite your snippet:
>>> Matrix = ['kys_q1a1','kys_q1a2','kys_q1a3','kys_q1a4','kys_q1a5','kys_q1a6']
>>> fixedlist = ['kys_q1a2', 'kys_q1a5']
>>> for i in fixedlist:
... print i, i in Matrix
...
kys_q1a2 True
kys_q1a5 True
>>>
And finally lets see some of the equality test: ==:
>>> 'a' == 'b'
False
>>> 'a' == 'a'
True
>>> 'a' == 'ab'
False
>>> '' in 'ab' # empty string is treated as a sub-string for any string
True
>>> '' == 'ab' # False as they are having different values
False
>>>
>>> 1 == 'ab'
False
>>> 1 == 1
True
>>>
Going with '==' is precise if you want to match exact string.

None value in python dictionary

Is it possible to check none value in dict
dict = {'a':'None','b':'12345','c':'None'}
My code
for k,v in d.items():
if d[k] != None:
print "good"
else:
print "Bad
Prints three good after executing above code snippet.
good
good
good
Required:If value is None than not printing good for dict key a and c.
Your none values are actually strings in your dictionary.
You can check for 'None'
or use actual python None value.
d = {'a':None,'b':'12345','c':None}
for k,v in d.items():
if d[k] is None:
print "good"
else:
print "Bad"
prints "good" 2 times
Or if you Have to use your current dictionary just change your check to look for 'None'
additionally dict is a python built in type so it is a good idea not to name variables dict
Define your dictionary with
d = {'a': None}
rather than
d = {'a': 'None'}
In the latter case, 'None' is just a string, not Python's None type. Also, test for None with the identity operator is:
for key, value in d.iteritems():
if value is None:
print "None found!"
def none_in_dict(d):
for _, value in d.items():
if value is None:
return True
return False
And the use is:
if none_in_dict(my_dict):
logger.error(my_err_msg)
Instead of using "if value is None" you can simply use
d = {'a':None, 'b':'12345', 'c':None, 'd':'None'}
for k, v in d.items():
if v:
print("good")
else:
print("bad")
"if v" will be True if there is any kind of value except None. Hence you don't have to explicitly use None keyword in if condition (if v is None).
Result:
bad
good
bad
good
In last case the value for key 'd' is 'None' - as a string not python value None

Categories