Shouldn’t Python none be semantically equal to SQL Null?

Asked

Viewed 141 times

2

That makes sense:

>>> if True==True:
...     print ('True')
...
True

That too:

>>> if False==False:
...     print ('True')
...
True

But that for me should return nothing, but returns True...

>>> if None==None:
...     print ('True')
...
True

My understanding was that None was with Null in SQL. Nothing is equal to Null, not even Null.

  • 3

    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 :)

  • 3

    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 make IS [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.

  • 4

    In python there is IS, it is possible to compare this way: None is None. It’s even a recommendation from PEP8.

  • 1

    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 and undefined, so much null === null how much undefined === undefined sane true - worst, null == undefined is true, but null === undefined is false) - 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 in True.

  • @Ricardopunctual, in ANSI SQL standard.

3 answers

5

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
  • 1

    +1 great references :)

  • @Ricardopunctual, you don’t know how gratifying it is to read this comment. Thank you very much.

3

Language defines like this, see:

The None keyword is used to define a null variable or an object. In Python, the keyword None is an object and is a data type of the Nonetype class.

We can assign None to any variable, but you cannot create other Nonetype objects.

Interesting facts:

None is not equal to False. None is not 0. None is not an empty string. Comparing None with anything will always return False, except None itself.

  • "Language defines like this, see" and where does it say that? would it make sense to put the source in the question

3

Python, None is a constant representing the only possible value class Nonetype.

That is, None is an object and its Nonetype class adopts the standard Singleton. When you compare None with None, you are literally comparing the same object. There is only one None. It is one keyword that represents a value.

Therefore, when this pattern is adopted, comparisons of this type do not need special rules to be understood. If you compare an object to itself, it makes sense for it to return True.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.