When I started to traverse a code of my friend, I came across two declarations of if clause.
one is declared as follows:
(CASE A)
if x not in ('a', 'b'):
pass
another is declared like this:
(CASE B)
if x != 'a' or x != 'b':
pass
(CASE C)
if x != 'a' and x != 'b':
pass
I've simplified the values as 'a' and 'b' but the actual values are complicated and pretty long. When I run them separately, I got the same output.
Which one does CASE A match with? CASE B or CASE C.
Also which form of writing is correct? using in or using equality operator.
They not the same, if you start from Case A, hopefully it is easy to see.
Consider case A.
x not in ('a', 'b')
This literally means, x is not equal to 'a' and x is not equal to 'b'. Or written as code.
x != 'a' and x != 'b'
That happens to be case C.
Case B on the other hand is exactly the same as C but it has an 'or' instead of an 'and'.
'or' does not perform the same operation as 'and', therefore case C is different.
x = 'a'
print("A", x not in ('a', 'b') )
print("B", x != 'a' or x != 'b')
print("C", x != 'a' and x != 'b')
In or statement you are saying that if you found any of the operands true then no need to check the other operands because the result will be true anyway.
In CASE B if x was (not 'a') then it's true and it'll not check if x is equals to 'b'.
You can simply test the cases by printing x as follows:
>>> x='b'
>>> if x not in ('a', 'b'): #CASE A (nothing printed when x='b')
... print(x)
...
>>> if x != 'a' or x!='b': #CASE B
... print(x)
...
b # The condition is true so x's value printed
>>> if x != 'a' and x!='b': #CASE C (nothing printed when x='b')
... print(x)
...
>>>
Here you can find that A and C have the same output (which is nothing).
Definitely, CASE C.
x not in ('a', 'b') means that x has not been appeared in given elements.
CASE B can be converted into correct form with:
if not (x == 'a' or x == 'b'):
pass
Related
This question already has answers here:
Compare if two variables reference the same object in python
(6 answers)
Closed 5 months ago.
The is operator does not match the values of the variables, but the
instances themselves.
What does it really mean?
I declared two variables named x and y assigning the same values in both variables, but it returns false when I use the is operator.
I need a clarification. Here is my code.
x = [1, 2, 3]
y = [1, 2, 3]
print(x is y) # It prints false!
You misunderstood what the is operator tests. It tests if two variables point the same object, not if two variables have the same value.
From the documentation for the is operator:
The operators is and is not test for object identity: x is y is true if and only if x and y are the same object.
Use the == operator instead:
print(x == y)
This prints True. x and y are two separate lists:
x[0] = 4
print(y) # prints [1, 2, 3]
print(x == y) # prints False
If you use the id() function you'll see that x and y have different identifiers:
>>> id(x)
4401064560
>>> id(y)
4401098192
but if you were to assign y to x then both point to the same object:
>>> x = y
>>> id(x)
4401064560
>>> id(y)
4401064560
>>> x is y
True
and is shows both are the same object, it returns True.
Remember that in Python, names are just labels referencing values; you can have multiple names point to the same object. is tells you if two names point to one and the same object. == tells you if two names refer to objects that have the same value.
Another duplicate was asking why two equal strings are generally not identical, which isn't really answered here:
>>> x = 'a'
>>> x += 'bc'
>>> y = 'abc'
>>> x == y
True
>>> x is y
False
So, why aren't they the same string? Especially given this:
>>> z = 'abc'
>>> w = 'abc'
>>> z is w
True
Let's put off the second part for a bit. How could the first one be true?
The interpreter would have to have an "interning table", a table mapping string values to string objects, so every time you try to create a new string with the contents 'abc', you get back the same object. Wikipedia has a more detailed discussion on how interning works.
And Python has a string interning table; you can manually intern strings with the sys.intern method.
In fact, Python is allowed to automatically intern any immutable types, but not required to do so. Different implementations will intern different values.
CPython (the implementation you're using if you don't know which implementation you're using) auto-interns small integers and some special singletons like False, but not strings (or large integers, or small tuples, or anything else). You can see this pretty easily:
>>> a = 0
>>> a += 1
>>> b = 1
>>> a is b
True
>>> a = False
>>> a = not a
>>> b = True
a is b
True
>>> a = 1000
>>> a += 1
>>> b = 1001
>>> a is b
False
OK, but why were z and w identical?
That's not the interpreter automatically interning, that's the compiler folding values.
If the same compile-time string appears twice in the same module (what exactly this means is hard to define—it's not the same thing as a string literal, because r'abc', 'abc', and 'a' 'b' 'c' are all different literals but the same string—but easy to understand intuitively), the compiler will only create one instance of the string, with two references.
In fact, the compiler can go even further: 'ab' + 'c' can be converted to 'abc' by the optimizer, in which case it can be folded together with an 'abc' constant in the same module.
Again, this is something Python is allowed but not required to do. But in this case, CPython always folds small strings (and also, e.g., small tuples). (Although the interactive interpreter's statement-by-statement compiler doesn't run the same optimization as the module-at-a-time compiler, so you won't see exactly the same results interactively.)
So, what should you do about this as a programmer?
Well… nothing. You almost never have any reason to care if two immutable values are identical. If you want to know when you can use a is b instead of a == b, you're asking the wrong question. Just always use a == b except in two cases:
For more readable comparisons to the singleton values like x is None.
For mutable values, when you need to know whether mutating x will affect the y.
is only returns true if they're actually the same object. If they were the same, a change to one would also show up in the other. Here's an example of the difference.
>>> x = [1, 2, 3]
>>> y = [1, 2, 3]
>>> print x is y
False
>>> z = y
>>> print y is z
True
>>> print x is z
False
>>> y[0] = 5
>>> print z
[5, 2, 3]
Prompted by a duplicate question, this analogy might work:
# - Darling, I want some pudding!
# - There is some in the fridge.
pudding_to_eat = fridge_pudding
pudding_to_eat is fridge_pudding
# => True
# - Honey, what's with all the dirty dishes?
# - I wanted to eat pudding so I made some. Sorry about the mess, Darling.
# - But there was already some in the fridge.
pudding_to_eat = make_pudding(ingredients)
pudding_to_eat is fridge_pudding
# => False
is and is not are the two identity operators in Python. is operator does not compare the values of the variables, but compares the identities of the variables. Consider this:
>>> a = [1,2,3]
>>> b = [1,2,3]
>>> hex(id(a))
'0x1079b1440'
>>> hex(id(b))
'0x107960878'
>>> a is b
False
>>> a == b
True
>>>
The above example shows you that the identity (can also be the memory address in Cpython) is different for both a and b (even though their values are the same). That is why when you say a is b it returns false due to the mismatch in the identities of both the operands. However when you say a == b, it returns true because the == operation only verifies if both the operands have the same value assigned to them.
Interesting example (for the extra grade):
>>> del a
>>> del b
>>> a = 132
>>> b = 132
>>> hex(id(a))
'0x7faa2b609738'
>>> hex(id(b))
'0x7faa2b609738'
>>> a is b
True
>>> a == b
True
>>>
In the above example, even though a and b are two different variables, a is b returned True. This is because the type of a is int which is an immutable object. So python (I guess to save memory) allocated the same object to b when it was created with the same value. So in this case, the identities of the variables matched and a is b turned out to be True.
This will apply for all immutable objects:
>>> del a
>>> del b
>>> a = "asd"
>>> b = "asd"
>>> hex(id(a))
'0x1079b05a8'
>>> hex(id(b))
'0x1079b05a8'
>>> a is b
True
>>> a == b
True
>>>
Hope that helps.
x is y is same as id(x) == id(y), comparing identity of objects.
As #tomasz-kurgan pointed out in the comment below is operator behaves unusually with certain objects.
E.g.
>>> class A(object):
... def foo(self):
... pass
...
>>> a = A()
>>> a.foo is a.foo
False
>>> id(a.foo) == id(a.foo)
True
Ref;
https://docs.python.org/2/reference/expressions.html#is-not
https://docs.python.org/2/reference/expressions.html#id24
As you can check here to a small integers. Numbers above 257 are not an small ints, so it is calculated as a different object.
It is better to use == instead in this case.
Further information is here: http://docs.python.org/2/c-api/int.html
X points to an array, Y points to a different array. Those arrays are identical, but the is operator will look at those pointers, which are not identical.
It compares object identity, that is, whether the variables refer to the same object in memory. It's like the == in Java or C (when comparing pointers).
A simple example with fruits
fruitlist = [" apple ", " banana ", " cherry ", " durian "]
newfruitlist = fruitlist
verynewfruitlist = fruitlist [:]
print ( fruitlist is newfruitlist )
print ( fruitlist is verynewfruitlist )
print ( newfruitlist is verynewfruitlist )
Output:
True
False
False
If you try
fruitlist = [" apple ", " banana ", " cherry ", " durian "]
newfruitlist = fruitlist
verynewfruitlist = fruitlist [:]
print ( fruitlist == newfruitlist )
print ( fruitlist == verynewfruitlist )
print ( newfruitlist == verynewfruitlist )
The output is different:
True
True
True
That's because the == operator compares just the content of the variable. To compare the identities of 2 variable use the is operator
To print the identification number:
print ( id( variable ) )
The is operator is nothing but an English version of ==.
Because the IDs of the two lists are different so the answer is false.
You can try:
a=[1,2,3]
b=a
print(b is a )#True
*Because the IDs of both the list would be same
A list of IP addresses are downloaded to a file and rename to Old_file. As days goes by device get update with more IPs(or deleted). Therefore, I download a new list of IP addresses to another file named as New_file
I then want to run a compare these two files and see what is not matching
Old_file = [1.1.1.1,
1.1.1.2,
1.1.1.3,
1.1.1.4,
1.1.1.6,]
new_file = [1.1.1.1,
1.1.1.2,
1.1.1.3,
1.1.1.5,
1.1.1.6]
return needs to 1.1.1.4, and stops there. But never from Old_file e.g: 1.1.1.5 (we need the results only from the New_file only)
I really hope this would explain.
Thanks in advance
Tony
For a simple element-wise comparison, you could do
def get_first_unequal(s0, s1):
for e0, e1 in zip(s0, s1): # assumes sequences are of equal length!
if e0 != e1:
print(f"unequal elements: '{e0}' vs. '{e1}'!")
return (e0, e1)
return None # all equal
a = ['a', 'b', 'c']
b = ['a', 'b', 'd']
get_first_unequal(a, b)
# unequal elements: 'c' vs. 'd'!
# ('c', 'd')
# --> to get a list of all unequal pairs, you could also use
# [(e0, e1) for (e0, e1) in zip(s0, s1) if e0 != e1]
If you want to go more sophisticated, as mentioned in the comments, difflib might be your way to go. to run e.g. a comparison of two sequences (which are the list of strings you read from the two txt files you want to compare):
import difflib
a = ['a', 'b', 'c']
b = ['s', 'b', 'c', 'd']
delta = difflib.context_diff(a, b)
for d in delta:
print(d)
gives
*** 1,3 ****
! a
b
c
--- 1,4 ----
! s
b
c
+ d
to check the difference between two strings, you could do something like (borrowing from here):
a = 'string1'
b = 'string 2'
delta = difflib.ndiff(a, b)
print(f"a -> b: {a} -> {b}")
for i, d in enumerate(delta):
if d[0] == ' ': # no difference
continue
elif d[0] == '-':
print(f"Deleted '{d[-1]}' from position {i}")
elif d[0] == '+':
print(f"Added '{d[-1]}' to position {i-1}")
gives
a -> b: string1 -> string 2
Deleted '1' from position 6
Added ' ' to position 6
Added '2' to position 7
If you're assuming that both files should be exactly identical, you can just iterate over the characters of the first and compare them to the second. I.e.
# check that they're the same length first
if len(Old_file) != len(New_file):
print('not the same!')
else:
for indx, char in enumerate(Old_file):
try:
# actually compare the characters
old_char = char
new_char = New_file[indx]
assert(old_char == new_char)
except IndexError:
# the new file is shorter than the old file
print('not the same!')
break # kill the loop
except AssertionError:
# the characters do not match
print('not the same!')
break # kill the loop
It's worth noting that there are faster ways to do this. You could look into performing a checksum, though it wouldn't tell you which parts are different only that they are different. If the files are large, the performance of doing the check one character at a time will be quite bad -- in that case you can try instead to compare blocks of data at a time.
Edit: re-reading your original question, you could definitely do this with a while loop. If you did, I would suggest basically the same strategy of checking each individual character. In that case you would manually need to increment the indx of course.
I am not super familiar with python, and I am having trouble reading this code. I have never seen this syntax, where there multiple statements are paired together (I think) on one line, separated by commas.
if L1.data < L2.data:
tail.next, L1 = L1, L1.next
Also, I don't understand assignment in python with "or": where is the conditional getting evaluated? See this example. When would tail.next be assigned L1, and when would tail.next be assigned L2?
tail.next = L1 or L2
Any clarification would be greatly appreciated. I haven't been able to find much on either syntax
See below
>>> a = 0
>>> b = 1
>>> a, b
(0, 1)
>>> a, b = b, a
>>> a, b
(1, 0)
>>>
It allows one to swap values without requiring a temporary variable.
In your case, the line
tail.next, L1 = L1, L1.next
is equivalent to
tail.next = L1
L1 = L1.next
In python when we write any comma separated values it creates a tuple (a kind of a datastructure).
a = 4,5
type(a) --> tuple
This is called tuple packing.
When we do:
a, b = 4,5
This is called tuple unpacking. It is equivalent to:
a = 4
b = 5
or is the boolean operator here.
Very Simple.
I want to add two lists with while or for in python3. so when writing the letter a the 1 appears and when writing the letter b the 2 appears and when writing the letter c the c is printed. Thanks in advance
x = input()
letter = ["a","b","c"]
number = [1,2,3]
I had a little trouble understanding the question, particularly this part:
"and when writing the letter c the c is printed"
I think you meant that you wanted 3 printed if the person types in c.
Here is some code that does that:
letter = ['a', 'b', 'c']
number = [1, 2, 3]
x = input("Please type a, b, or c > ")
if x in letter:
for index, value in enumerate(letter):
if x == value:
print(number[index])
else:
print("The value you typed is not in my list")
Alright. So, I have a function that I'm testing out. It has two returns. Here is the code:
x = 5
y = 7
def test(w, z):
if w == 5 and z == 7:
print("good!")
w = 6
z = 12
return(w, z)
test(x, y)
Alright so, there's my test function. It takes 'x' and 'y' and it does some stuff with them, and then it changes them if both are equal to the numbers.
However, I might want to keep that information that 'w' became 6 and 'z' became 12. In this case, I want 'w's value to equal 'x's. Likewise with 'y' and 'z'.
Unfortunately, when I try what I had already learned from stackOverflow:
x = test(x, y)
print(x)
I would get (6, 12). How can I make it so that 'x' gets 'w's value and 'y' gets 'z's value?
Do like this:
x,y = test(x, y)