This behavior occurs because the language was defined like this.
In the official language documentation Data Template: Special Method Names is written:
A class can implement certain operations that are called by
special syntax (such as arithmetic or subscript operations and
slice), defining methods with special names. This is the approach
Python for operator overload, allowing classes
define their own behaviour towards the operators of the
language.
Just below are defined the methods of comparison:
object.__lt__(self, other)
object.__le__(self, other)
object.__eq__(self, other)
object.__ne__(self, other)
object.__gt__(self, other)
object.__ge__(self, other)
These are the so-called methods of "rich comparison". The correspondence
between operator symbols and method names is as follows:
x<y
flame x.__lt__(y)
x<=y
flame x.__le__(y)
x==y
flame x.__eq__(y)
x!=y
flame x.__ne__(y)
x>y
flame x.__gt__(y)
x>=y
flamex.__ge__(y)
Replacing the comparison None==None
by means of the relevant method of comparison:
>>> print(None.__eq__(None))
True
Now a care must be taken when comparing None
with other values:
>>> print(None == False)
False
>>> print(None == True)
False
This is because the comparison method None.__eq__()
for values other than None
is not defined and by default, object
implements __eq__()
using is
, returning NotImplemented
in the case of a false comparison: True if x is y else NotImplemented
, implying that anything other than None
compared to None
is False
.
>>> print(None.__eq__(True))
NotImplemented
>>> print(None.__eq__(False))
NotImplemented
reinforces the alert made in PEP8:
Comparisons with singletons as None
should always be done with is
or
not
, never with equality operators
Also, be careful when writing if x
when you really mean if x not is None
- for example, when testing whether a variable or argument whose default is None
was set to some other value. The other value may have a type (like a container) that can be false in a boolean context!
Take this example from w3schools.com illustrating the situation:
>>> x = None
>>> if x:
... print("Você pensa que None é True?")
... elif x is False:
... print ("Você pensa que None é False?")
... else:
... print("None não é True ou False, None apenas None...")
None não é True ou False, None apenas None...
And it’s no use forcing a class to emulate a logical value None
:
>>> class teste():
... def __bool__(self):
... return None
>>> t = teste()
>>> print(bool(t))
Traceback (most recent call last):
File "main.py", line 6, in <module>
print(bool(t))
TypeError: __bool__ should return bool, returned NoneType
and which "sql" would that be?
mysql
,sql-server
,oracle
? depends on the/Provider driver.sql-server
has a driver that returns a type "Dbnull" for example :)– Ricardo Pontual
Each language implements in a way, there is no guarantee of equivalence between them, only the more or less general behavior of the null value to be treated in a special way in relation to non-nulls. See that if it was to be equal to SQL the programming language would have to have the operator
IS
to makeIS [NOT] NULL
and not== NULL
, The languages I know don’t usually have that. Nor is the comparison behavior by equality the same between languages or even between different types of data within the same language, being overwritten or overwritten for example.– Piovezan
In python there is IS, it is possible to compare this way:
None is None
. It’s even a recommendation from PEP8.– Danizavtz
Why do you think you should? Each language is created in a way, and in practice each one creates the definitions you want, in the way you want, with the meaning you think most appropriate (say Javascript, which has
null
andundefined
, so muchnull === null
how muchundefined === undefined
sanetrue
- worst,null == undefined
istrue
, butnull === undefined
isfalse
) - In the case of Python,None
is a value. Of course, it is used to designate the "absence of value", but it itself is a value, and so comparing it to itself results inTrue
.– hkotsubo
@Ricardopunctual, in ANSI SQL standard.
– Luis Santos