<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Re: &amp;quot;If not Null and not empty string&amp;quot; paradox - help me figure it out? in Python Questions</title>
    <link>https://community.esri.com/t5/python-questions/quot-if-not-null-and-not-empty-string-quot-paradox/m-p/1618194#M74279</link>
    <description>&lt;P&gt;Although SQL NULL gets mapped to Python None, they are not logically identical because Python by default does not implement three-value logic.&amp;nbsp; Whereas SQL logical operators in most systems support TRUE/FALSE/NULL, Python logical operators only support True/False.&amp;nbsp; From&amp;nbsp;&lt;SPAN&gt;&lt;A href="https://docs.python.org/3/reference/expressions.html#boolean-operations" target="_self"&gt;6. Expressions - Python 3.y.z documentation:&lt;/A&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;BLOCKQUOTE&gt;&lt;P&gt;In the context of Boolean operations, and also when expressions are used by control flow statements, the following values are interpreted as false: False, None, numeric zero of all types, and empty strings and containers (including strings, tuples, lists, dictionaries, sets and frozensets).&lt;/P&gt;&lt;/BLOCKQUOTE&gt;&lt;P&gt;&lt;SPAN&gt;The issue isn't that your logic is incorrect, or that the code is incorrect (although it may be), it is that you are trying to interpret results for Python logical expressions as if they were SQL logical expressions.&lt;/SPAN&gt;&lt;/P&gt;</description>
    <pubDate>Sat, 24 May 2025 17:02:42 GMT</pubDate>
    <dc:creator>JoshuaBixby</dc:creator>
    <dc:date>2025-05-24T17:02:42Z</dc:date>
    <item>
      <title>"If not Null and not empty string" paradox - help me figure it out?</title>
      <link>https://community.esri.com/t5/python-questions/quot-if-not-null-and-not-empty-string-quot-paradox/m-p/1618009#M74269</link>
      <description>&lt;P&gt;Hello,&lt;/P&gt;&lt;P&gt;I am adding something to a script I wrote a few years ago, and in the process, I happened to notice some logic in the script that I would think is wrong, yet it works as desired.&amp;nbsp; This is breaking my brain!&amp;nbsp; While it is apparently not an actual problem, I would love some help in understanding it.&amp;nbsp; (I can't recall why I wrote it this way a few years ago, so my memory is no help here.)&lt;/P&gt;&lt;P&gt;This part of the script uses an arcpy update cursor to populate certain fields in a feature class, depending on what the existing values are.&amp;nbsp; If the State field is Null OR an empty string, it is supposed to be populated with "CA".&amp;nbsp; In other words, all records should have "CA" in this State field.&amp;nbsp; The script is supposed to ONLY edit records that really need editing, which is why I'm using criteria to pick which records get edited, rather than just doing a field calculation on the entire feature class.&lt;/P&gt;&lt;P&gt;However, the code is saying "if it is Null AND it is NOT an empty string, then make it CA."&amp;nbsp; I don't get it.&amp;nbsp; I would think that only Nulls would be picked... or maybe nothing at all.&amp;nbsp; &amp;nbsp;&lt;/P&gt;&lt;P&gt;But the script does correctly populate the field with "CA" if there was an empty string there.&amp;nbsp; I don't understand how this is possible.&amp;nbsp; Any thoughts???&lt;/P&gt;&lt;P&gt;Here is the code:&lt;/P&gt;&lt;LI-CODE lang="python"&gt;# If State is blank or null, make it "CA"
if row[field_index_dict.get("State")] is None and row[field_index_dict.get("State")] != '':
    row[field_index_dict.get("State")] = "CA"
    field_uc.updateRow(row)&lt;/LI-CODE&gt;&lt;P&gt;Thank you for reading!&lt;/P&gt;</description>
      <pubDate>Fri, 23 May 2025 19:06:32 GMT</pubDate>
      <guid>https://community.esri.com/t5/python-questions/quot-if-not-null-and-not-empty-string-quot-paradox/m-p/1618009#M74269</guid>
      <dc:creator>AllenDailey1</dc:creator>
      <dc:date>2025-05-23T19:06:32Z</dc:date>
    </item>
    <item>
      <title>Re: "If not Null and not empty string" paradox - help me figure it out?</title>
      <link>https://community.esri.com/t5/python-questions/quot-if-not-null-and-not-empty-string-quot-paradox/m-p/1618016#M74270</link>
      <description>&lt;P&gt;You just have a syntax error in your condition:&lt;/P&gt;&lt;LI-CODE lang="python"&gt;- if row[field_index_dict.get("State")] is None and row[field_index_dict.get("State")] != '':
+ if not row[field_index_dict.get("State")]:
    row[field_index_dict.get("State")] = "CA"
    field_uc.updateRow(row)&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Empty string and None both evaluate to False so you can just say `if not` and it'll work. Your original logic is also evaluating to True if the sate is both None and not an empty string (which is always True)&lt;/P&gt;</description>
      <pubDate>Fri, 23 May 2025 21:24:38 GMT</pubDate>
      <guid>https://community.esri.com/t5/python-questions/quot-if-not-null-and-not-empty-string-quot-paradox/m-p/1618016#M74270</guid>
      <dc:creator>HaydenWelch</dc:creator>
      <dc:date>2025-05-23T21:24:38Z</dc:date>
    </item>
    <item>
      <title>Re: "If not Null and not empty string" paradox - help me figure it out?</title>
      <link>https://community.esri.com/t5/python-questions/quot-if-not-null-and-not-empty-string-quot-paradox/m-p/1618098#M74273</link>
      <description>&lt;P&gt;I prefer dump and proceed&lt;/P&gt;&lt;LI-CODE lang="python"&gt;a = ["", " ", None]
val = ["A", "", "B", " ", None]
for i in val:
    if i in a:
        print("ignore")
    else:
        print(i)
        
A
ignore
B
ignore
ignore&lt;/LI-CODE&gt;</description>
      <pubDate>Fri, 23 May 2025 20:48:30 GMT</pubDate>
      <guid>https://community.esri.com/t5/python-questions/quot-if-not-null-and-not-empty-string-quot-paradox/m-p/1618098#M74273</guid>
      <dc:creator>DanPatterson</dc:creator>
      <dc:date>2025-05-23T20:48:30Z</dc:date>
    </item>
    <item>
      <title>Re: "If not Null and not empty string" paradox - help me figure it out?</title>
      <link>https://community.esri.com/t5/python-questions/quot-if-not-null-and-not-empty-string-quot-paradox/m-p/1618193#M74278</link>
      <description>&lt;P&gt;From both a practice (&amp;nbsp;&lt;A href="https://peps.python.org/pep-0008/" target="_blank"&gt;https://peps.python.org/pep-0008/&lt;/A&gt;&amp;nbsp;) and performance perspective, checking for None should be done using "is" or "is not".&lt;/P&gt;</description>
      <pubDate>Sat, 24 May 2025 16:23:12 GMT</pubDate>
      <guid>https://community.esri.com/t5/python-questions/quot-if-not-null-and-not-empty-string-quot-paradox/m-p/1618193#M74278</guid>
      <dc:creator>JoshuaBixby</dc:creator>
      <dc:date>2025-05-24T16:23:12Z</dc:date>
    </item>
    <item>
      <title>Re: "If not Null and not empty string" paradox - help me figure it out?</title>
      <link>https://community.esri.com/t5/python-questions/quot-if-not-null-and-not-empty-string-quot-paradox/m-p/1618194#M74279</link>
      <description>&lt;P&gt;Although SQL NULL gets mapped to Python None, they are not logically identical because Python by default does not implement three-value logic.&amp;nbsp; Whereas SQL logical operators in most systems support TRUE/FALSE/NULL, Python logical operators only support True/False.&amp;nbsp; From&amp;nbsp;&lt;SPAN&gt;&lt;A href="https://docs.python.org/3/reference/expressions.html#boolean-operations" target="_self"&gt;6. Expressions - Python 3.y.z documentation:&lt;/A&gt;&lt;/SPAN&gt;&lt;/P&gt;&lt;BLOCKQUOTE&gt;&lt;P&gt;In the context of Boolean operations, and also when expressions are used by control flow statements, the following values are interpreted as false: False, None, numeric zero of all types, and empty strings and containers (including strings, tuples, lists, dictionaries, sets and frozensets).&lt;/P&gt;&lt;/BLOCKQUOTE&gt;&lt;P&gt;&lt;SPAN&gt;The issue isn't that your logic is incorrect, or that the code is incorrect (although it may be), it is that you are trying to interpret results for Python logical expressions as if they were SQL logical expressions.&lt;/SPAN&gt;&lt;/P&gt;</description>
      <pubDate>Sat, 24 May 2025 17:02:42 GMT</pubDate>
      <guid>https://community.esri.com/t5/python-questions/quot-if-not-null-and-not-empty-string-quot-paradox/m-p/1618194#M74279</guid>
      <dc:creator>JoshuaBixby</dc:creator>
      <dc:date>2025-05-24T17:02:42Z</dc:date>
    </item>
    <item>
      <title>Re: "If not Null and not empty string" paradox - help me figure it out?</title>
      <link>https://community.esri.com/t5/python-questions/quot-if-not-null-and-not-empty-string-quot-paradox/m-p/1618207#M74280</link>
      <description>&lt;P&gt;There's basically no performance difference between using a raw not (calling __bool__()) and is not (calling id(a)&amp;nbsp; !=&amp;nbsp; id(b)). I only dropped the is because forcing the condition to check the boolean in this case simplifies the condition from a readability standpoint. We know that Null/None and '' both evaluate to False when __bool__() is called.&lt;/P&gt;&lt;P&gt;I wouldn't recommend this pattern when dealing with arbitrary objects (as the __bool__ method can be overwritten), but since we know the type signature of the input value is Optional(str), we can just use the raw `not`.&lt;/P&gt;&lt;P&gt;You could change the condition to be val is None or val == '', but why add a second condition when one will suffice? Since the condition will likely be short circuited anyways, we could write it in a way that reflects that and combines the checks into a single statement.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Testing:&lt;/P&gt;&lt;LI-CODE lang="python"&gt;from random import choice

opts = ["Something", "", None]

def raw_not():
    val = choice(opts)
    return not val

def is_not():
    val = choice(opts)
    return val is not None or val != ''&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Disassembled:&lt;/P&gt;&lt;LI-CODE lang="c"&gt;raw_not
  5           0 RESUME                   0

  6           2 LOAD_GLOBAL              1 (NULL + choice)
             12 LOAD_GLOBAL              2 (opts)
             22 CALL                     1
             30 STORE_FAST               0 (val)

  7          32 LOAD_FAST                0 (val)
             34 UNARY_NOT
             36 RETURN_VALUE

-----------------------------------------------------------
is_not
 9           0 RESUME                   0

 10           2 LOAD_GLOBAL              1 (NULL + choice)
             12 LOAD_GLOBAL              2 (opts)
             22 CALL                     1
             30 STORE_FAST               0 (val)

 11          32 LOAD_FAST                0 (val)
             34 LOAD_CONST               0 (None)
             36 IS_OP                    1
             38 COPY                     1
             40 POP_JUMP_IF_TRUE         5 (to 52)
             42 POP_TOP
             44 LOAD_FAST                0 (val)
             46 LOAD_CONST               1 ('')
             48 COMPARE_OP              55 (!=)
        &amp;gt;&amp;gt;   52 RETURN_VALUE&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Performance:&lt;/P&gt;&lt;LI-CODE lang="c"&gt;%timeit raw_not()
298 ns ± 0.81 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)

%timeit is_not()
303 ns ± 5.04 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;You can see that the python bytecode for the raw_not function is a lot simpler and only calls the UNARY_NOT function without adding any branching. Performance wise, it's a wash, but since there's branching in the short circuited version, the state of the data can effect the performance (checking for is None when most records are empty string will add an extra step for each record).&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;This is all beyond the scope for this question though lol, Everyone should definitely read PEP008, and do their best to abide by it, but I don't think that it should necessarily be used as gospel in all cases. Use your best judgement and if you feel that breaking PEP008 is valid in a certain case, make a note of it and be ready to justify it!&lt;/P&gt;</description>
      <pubDate>Sat, 24 May 2025 23:29:32 GMT</pubDate>
      <guid>https://community.esri.com/t5/python-questions/quot-if-not-null-and-not-empty-string-quot-paradox/m-p/1618207#M74280</guid>
      <dc:creator>HaydenWelch</dc:creator>
      <dc:date>2025-05-24T23:29:32Z</dc:date>
    </item>
    <item>
      <title>Re: "If not Null and not empty string" paradox - help me figure it out?</title>
      <link>https://community.esri.com/t5/python-questions/quot-if-not-null-and-not-empty-string-quot-paradox/m-p/1618219#M74281</link>
      <description>&lt;P&gt;Stripping the test down to the most basic steps and removing IPython, I see equality checking costing quite a bit more than identity checking.&lt;/P&gt;&lt;LI-CODE lang="python"&gt;C:\&amp;gt;python -m timeit -n 1000000 -v "value = None; value != None"
raw times: 34.2 msec, 34.1 msec, 33.6 msec, 33.7 msec, 33.4 msec

1000000 loops, best of 5: 33.4 nsec per loop

C:\&amp;gt;python -m timeit -n 1000000 -v "value = None; value is not None"
raw times: 21.9 msec, 21.9 msec, 21.9 msec, 21.9 msec, 22.3 msec

1000000 loops, best of 5: 21.9 nsec per loop&lt;/LI-CODE&gt;&lt;P&gt;Granted, both equality checks and identity checks are extremely fast for Python built-in constants, so on a practical level the choice would not make a difference in the overall performance of a Python function or code block.&amp;nbsp; I only mentioned performance to point out there is no performance benefit to go against best practice.&lt;/P&gt;&lt;P&gt;I agree that PEP008 should not be followed dogmatically, but I cannot imagine a Python core developer advocating for an equality check over an identity check when it comes to a singleton.&lt;/P&gt;&lt;P&gt;This might just be an-agree-to-disagree situation, but the discussion is good to have regardless.&lt;/P&gt;</description>
      <pubDate>Sun, 25 May 2025 16:59:01 GMT</pubDate>
      <guid>https://community.esri.com/t5/python-questions/quot-if-not-null-and-not-empty-string-quot-paradox/m-p/1618219#M74281</guid>
      <dc:creator>JoshuaBixby</dc:creator>
      <dc:date>2025-05-25T16:59:01Z</dc:date>
    </item>
    <item>
      <title>Re: "If not Null and not empty string" paradox - help me figure it out?</title>
      <link>https://community.esri.com/t5/python-questions/quot-if-not-null-and-not-empty-string-quot-paradox/m-p/1618222#M74282</link>
      <description>&lt;P&gt;I think there was a miscommunication here, I'd never recommend that someone use equality over identity for checking against sentinel values. My example was just inverting the value since all conditions that the original poster wanted to check for evaluate to False. That check is actually even faster than the identity check:&lt;/P&gt;&lt;LI-CODE lang="c"&gt;python -m timeit -n 1000000 -v "val = None; not val"
raw times: 10.9 msec, 10.9 msec, 10.8 msec, 10.9 msec, 10.8 msec

python -m timeit -n 1000000 -v "val = None; val is not None"
raw times: 12.6 msec, 11.5 msec, 11.5 msec, 11.4 msec, 11.5 msec&lt;/LI-CODE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Disassembled, you can see the unary not saves on a load:&lt;/P&gt;&lt;LI-CODE lang="c"&gt;&amp;gt;&amp;gt;&amp;gt; val = None 
&amp;gt;&amp;gt;&amp;gt; dis.dis("not val")
  0           0 RESUME                   0

  1           2 LOAD_NAME                0 (val)
              4 UNARY_NOT
              6 RETURN_VALUE

&amp;gt;&amp;gt;&amp;gt; dis.dis("val is not None")
  0           0 RESUME                   0

  1           2 LOAD_NAME                0 (val)
              4 LOAD_CONST               0 (None)
              6 IS_OP                    1
              8 RETURN_VALUE&lt;/LI-CODE&gt;</description>
      <pubDate>Sun, 25 May 2025 19:24:52 GMT</pubDate>
      <guid>https://community.esri.com/t5/python-questions/quot-if-not-null-and-not-empty-string-quot-paradox/m-p/1618222#M74282</guid>
      <dc:creator>HaydenWelch</dc:creator>
      <dc:date>2025-05-25T19:24:52Z</dc:date>
    </item>
    <item>
      <title>Re: "If not Null and not empty string" paradox - help me figure it out?</title>
      <link>https://community.esri.com/t5/python-questions/quot-if-not-null-and-not-empty-string-quot-paradox/m-p/1619304#M74299</link>
      <description>&lt;P&gt;I tried replicating this with the default "Point Notes" layer template and the following code but what I get is the expected behaviour: nulls pass but empty strings fail&lt;/P&gt;&lt;LI-CODE lang="python"&gt;with arcpy.da.UpdateCursor('Point Notes', "Name") as cur:
    for row in cur:
        if row[0] is None and row[0] != "":
            print(f"[{row[0]}] passed")
        else:
            print(f"[{row[0]}] failed")

&amp;gt;&amp;gt;&amp;gt;[None] passed
&amp;gt;&amp;gt;&amp;gt;[] failed&lt;/LI-CODE&gt;&lt;P&gt;As you'd expect, it doesn't matter what the right hand expression is or what data's in the field, because the None check fails and stops the condition outright. All I can suggest is taking a closer look at your data or how that field index dict is constructed, I can't figure out why this is happening from the context provided.&lt;/P&gt;</description>
      <pubDate>Thu, 29 May 2025 15:51:56 GMT</pubDate>
      <guid>https://community.esri.com/t5/python-questions/quot-if-not-null-and-not-empty-string-quot-paradox/m-p/1619304#M74299</guid>
      <dc:creator>DavidSolari</dc:creator>
      <dc:date>2025-05-29T15:51:56Z</dc:date>
    </item>
    <item>
      <title>Re: "If not Null and not empty string" paradox - help me figure it out?</title>
      <link>https://community.esri.com/t5/python-questions/quot-if-not-null-and-not-empty-string-quot-paradox/m-p/1619309#M74300</link>
      <description>&lt;P&gt;Thank you!&lt;/P&gt;&lt;P&gt;I changed my code to simply "if not row[...]:" and it works.&amp;nbsp; Thanks for the reminder about this possibility.&lt;/P&gt;</description>
      <pubDate>Thu, 29 May 2025 16:05:21 GMT</pubDate>
      <guid>https://community.esri.com/t5/python-questions/quot-if-not-null-and-not-empty-string-quot-paradox/m-p/1619309#M74300</guid>
      <dc:creator>AllenDailey1</dc:creator>
      <dc:date>2025-05-29T16:05:21Z</dc:date>
    </item>
  </channel>
</rss>

