I have an API in the Django project I am working on that sends commands to devices. The API expects a POST request with data containing something like {"command": "activate"}. A few minutes ago I found this bit of code in the view function for the API
... ommitting the DRF viewset class def for brevity ...
def command(self, request):
if 'command' in request.data and request.data['command'] is not 'activate':
... do things that we need to do to send the activate command...
I figured that someone (most likely myself) made a logic error and fixed it to request.data['command'] is 'activate', but immediately realized that the API actually works as is. That is this if statement evaluates as True and commands do get sent even though it clearly states request.data['command'] is not 'activate'
So I started debugging and eventually found out that request.data['command'] != 'activate' returns False as expected and breaks the code, but request.data['command'] is not 'activate' returns True. As far as I can tell, the difference between is not and != is that is not compares identity where != compares value. But, again, as far as I know, literals should have the same identity no matter where they come from. A quick test in ipython seems to confirm this
In [1] x = {'command': 'activate'}
In [2] x['command'] is 'activate'
Out[2] True
In [3] x['command'] is not 'activate'
Out[3] False
What the hell is going on? Why doesn't it work in the view?
Do not rely on string comparison by identity, in any cases. The fact that it appears to work sometimes is due to an implementation detail of CPython called string interning. The rules governing whether a given string will be interned or not are very complicated, and subject to change without notice.
For example, with a slight modification of your original example we can change the behaviour:
>>> x = {'command': 'activate.'}
>>> x['command'] is 'activate.'
False
Use == and != for string comparisons.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With