Why do empty string and None evaluate differently? [duplicate] - python

This question already has answers here:
Why is '' > 0 True in Python 2?
(2 answers)
Closed 8 years ago.
Why do those two evaluate differently?
In [34]: a = ''
In [35]: if a or a >=0:
print 'y'
....:
y
In [36]: a = None
In [37]: if a or a >=0:
print 'y'
....:
I thought an empty string also evaluates to None (I know they are not the same)? Or is it just falsy and thus evaluates to 0 (which then evaluates to None if tested like if a: do something)?

It's because in CPython int comes before string
from docs:
CPython implementation detail: Objects of different types except numbers are ordered by their type names; objects of the same types that don’t support proper comparison are ordered by their address.
so:
>>> '1' > 1
True

Related

The is keyword in python [duplicate]

This question already has answers here:
Why does comparing strings using either '==' or 'is' sometimes produce a different result?
(15 answers)
"is" operator behaves unexpectedly with integers
(11 answers)
Is there a difference between "==" and "is"?
(13 answers)
Is there any difference between "foo is None" and "foo == None"?
(12 answers)
Closed 2 years ago.
The is keyword in python is described like that:
is is used in Python for testing object identity. While the == operator is used to test if two variables are equal or not, is is used to test if the two variables refer to the same object.
It returns True if the objects are identical and False if not.
>>> True is True
True
>>> False is False
True
>>> None is None
True
We know that there is only one instance of True, False and None in Python, so they are identical.
>>> [] == []
True
>>> [] is []
False
>>> {} == {}
True
>>> {} is {}
False
An empty list or dictionary is equal to another empty one. But they are not identical objects as they are located separately in memory. This is because list and dictionary are mutable (value can be changed).
>>> '' == ''
True
>>> '' is ''
True
>>> () == ()
True
>>> () is ()
True
Unlike list and dictionary, string and tuple are immutable (value cannot be altered once defined). Hence, two equal string or tuple are identical as well. They refer to the same memory location.
Till now there is no problem. My issue is that I have two instances of two variables as string type
a = 'yasser'
b = 'yasser'
a is b
This code returns True
while
a = 'yasser!'
b = 'yasser!'
a is b
This returns False althought these are of string types. Any explanation..?
The 'is' keyword evaluates to true if the true arguments are from the same object. In the cases you had above, all of the ones that evaluate to true are from the same object, however, while those two strings are identical, they are not the same object. You can read more about it here.

What does the `in` operator in Python use for comparison? [duplicate]

This question already has answers here:
Checking for NaN presence in a container
(2 answers)
Closed 2 years ago.
I am trying to understand what mechanism is used by in to compare the needle and the haystack.
[] in ([],[],[]) is True, so it cannot be is, because [] is [] is False
But math.nan in ([],[],math.nan) is True, too, so it cannot be ==, because math.nan==math.nan is False.
If it is neither == (comparison for equal value) nor is (comparison for object identity), what is it?
As the docs say:
For container types such as list, tuple, set, frozenset, dict, or collections.deque, the expression x in y is equivalent to any(x is e or x == e for e in y).
So, it's both.

Why does this str strict comparison fail in Python? [duplicate]

This question already has answers here:
Why does comparing strings using either '==' or 'is' sometimes produce a different result?
(15 answers)
Closed 8 years ago.
I have this code in a decorator:
is_local_valid = ['system_id', 'server_id', 'sensor_id']
local_params = [x for x in is_local_valid if x in kwargs.keys() and kwargs[x].lower() is 'local'] + [y for y in args if y.lower() is 'local']
if local_params == []:
raise AssertionError("Tried to access the database from a non connected profile")
I noticed that the is infix operator for comparing two strings returns False in this case, even when kwargs[x].lower() equals to local. The == operator does return True, though. Both are str, of course.
Any clue on what's going on?
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. x is not y yields the inverse truth value.
>>> id('local')
42745112
>>> a = {1: 'locAl'}
>>> id(a[1].lower())
53363408
They are not the same object
a is b determines whether two names a and b reference the same object (i.e. id(a) == id(b)). a == b determines whether they have equal values. It is rarely a good idea to compare strings with is; use == instead:
>>> "".join("hello")
'hello'
>>> "hello" is "".join("hello")
False
>>> "hello" == "".join("hello")
True
The only general case for comparison with is would be for None, e.g.:
if a is None:

Why does string > int evaluate to True? [duplicate]

This question already has answers here:
How does Python 2 compare string and int? Why do lists compare as greater than numbers, and tuples greater than lists?
(2 answers)
Closed 9 years ago.
How come a check of string > int evaluates to True?
>>> strver = "1"
>>> ver = 1
>>> strver > ver
True
>>> strVer2 = "whaat"
>>> strVer2 > ver
True
Did some more experimenting:
>>> ver3 = 0
>>> strVer2 > ver3
True
I think there should be an error when trying to compare but it seems like nothing is built to handle such an error, or assert should be used but that can be dangerous if python code is being run with -O flag!
Source: How does Python compare string and int?, which in turn quotes the CPython manual:
CPython implementation detail: Objects of different types except numbers are ordered by their type names; objects of the same types that don’t support proper comparison are ordered by their address.
From the SO answer:
When you order two incompatible types where neither is numeric, they are ordered by the alphabetical order of their typenames:
>>> [1, 2] > 'foo' # 'list' < 'str'
False
>>> (1, 2) > 'foo' # 'tuple' > 'str'
True
>>> class Foo(object): pass
>>> class Bar(object): pass
>>> Bar() < Foo()
True
...so, it's because 's' comes after 'i' in the alphabet! Luckily, though, this slightly odd behavior has been "fixed" in the implementation of Python 3.x:
In Python 3.x the behaviour has been changed so that attempting to order an integer and a string will raise an error:
Seems to follow the principle of least astonishment a little better now.

Is there shorthand for returning a default value if None in Python? [duplicate]

This question already has answers here:
Is there a Python equivalent of the C# null-coalescing operator?
(12 answers)
Closed 7 years ago.
In C#, I can say x ?? "", which will give me x if x is not null, and the empty string if x is null. I've found it useful for working with databases.
Is there a way to return a default value if Python finds None in a variable?
You could use the or operator:
return x or "default"
Note that this also returns "default" if x is any falsy value, including an empty list, 0, empty string, or even datetime.time(0) (midnight).
return "default" if x is None else x
try the above.
You can use a conditional expression:
x if x is not None else some_value
Example:
In [22]: x = None
In [23]: print x if x is not None else "foo"
foo
In [24]: x = "bar"
In [25]: print x if x is not None else "foo"
bar
You've got the ternary syntax x if x else '' - is that what you're after?

Categories