In code reviews and forum threads, one of the most common beginner questions is how to compare values correctly in Python. The confusion usually starts when people mix up equality vs identity, hit floating-point edge cases, or move from plain Python to libraries like NumPy or pandas where comparisons behave differently.
I’m new to Python and keep seeing two different ways to test inequality: != and is not. What is the correct way to check for not equal in Python, and what are the common pitfalls with numbers, strings, lists, None, and libraries like NumPy or pandas? Also, are there best practices for readability and performance?
Python gives you two main concepts here: value inequality and object identity inequality. Use them for different purposes.
- Value not equal:
a != bchecks if two values are not equal. This uses the same semantics as==and calls__eq__under the hood. - Identity not equal:
a is not bchecks if two references point to different objects in memory. This does not compare the value of the item, just whether or not they are the same item.
# Value inequality
3 != 4 # True
[1, 2] != [1, 2] # False, lists have the same content
# Identity inequality
a = [1, 2]
b = [1, 2]
a is not b # True, different list objects even though values are equalCode language: PHP (php)
- Comparing to None: Use identity, not equality:
if x is not None. This is the canonical style and avoids surprises if__eq__is overloaded. - Floats and precision: Avoid direct comparisons when rounding error matters. Use
math.iscloseand invert the result:
# Value inequality
3 != 4 # True
[1, 2] != [1, 2] # False, lists have the same content
# Identity inequality
a = [1, 2]
b = [1, 2]
a is not b # True, different list objects even though values are equalCode language: PHP (php)
- NaN edge case:
float('nan') != float('nan')is True by definition. Usemath.isnanto detect NaN. - Strings and case:
"Hello" != "hello” is True. For case-insensitive checks, normalize:
s1.lower() != s2.lower()
# or better for i18n
s1.casefold() != s2.casefold()Code language: PHP (php)
- Custom classes: In Python 3,
__ne__is automatically inferred as the inverse of__eq__if you only define__eq__. Dataclasses do this for you:
from dataclasses import dataclass
@dataclass(eq=True)
class User:
id: int
name: str
User(1, "A") != User(2, "A") # TrueCode language: CSS (css)
- Collections: Lists, tuples, sets, and dicts compare by content. For dicts, both keys and values must match to be equal.
{'a': 1} != {'a': 2} # True
{1, 2} != {2, 1} # False, sets ignore orderCode language: PHP (php)
- NumPy and pandas: != is elementwise, yielding arrays or Series of booleans. Use any/all:
import numpy as np
a = np.array([1, 2, 3])
b = np.array([1, 9, 3])
(a != b).any() # True if any element differsCode language: PHP (php)
- Chained comparisons:
x != y != zmeans(x != y)and(y != z). It does not mean all three are distinct. For that, uselen({x, y, z}) == 3. - Readability: Prefer
x != yovernot (x == y). The first is clearer and equivalent.
# Integers
5 != 5 # False
5 is not 5 # False for small ints due to interning, but don't rely on this
# None checks
value is not None
# Strings
"a" != "A" # True
"a".casefold() != "A".casefold() # False
# Floats
from math import isclose, isnan
not isclose(0.30000000000000004, 0.3) # False
x = float('nan')
x != x # True
isnan(x) # True
# Lists
[1, 2] != [2, 1] # TrueCode language: PHP (php)
If you manage images or videos programmatically, you can use these patterns to filter assets and enforce rules. For example, fetch assets and select those whose format is not equal to PNG, then transform or download them.
# Example using Cloudinary's Python SDK concepts
import cloudinary
import cloudinary.search
import cloudinary.uploader
cloudinary.config(
cloud_name="your_cloud",
api_key="your_key",
api_secret="your_secret"
)
# Fetch recent images
results = cloudinary.search.Search() \
.expression("resource_type:image") \
.max_results(100) \
.execute()
# Filter assets whose format is not equal to 'png'
non_png_assets = [res for res in results["resources"] if res.get("format") != "png"]
# Convert them on upload or via transformation if needed
for asset in non_png_assets:
public_id = asset["public_id"]
# Example: deliver as PNG by transformation, or re-upload as needed
# You can also automate conversions or use the Tools page for quick tests:
# https://cloudinary.com/tools
# Delivered URL could be:
# https://res.cloudinary.com/<cloud>/image/upload/f_png/<public_id>.jpg
passCode language: PHP (php)
For quick one-off conversions or tests without writing code, explore Cloudinary Tools.
- Use
!=for value inequality,is notfor identity checks. - Prefer
x is not Nonewhen testing against None. - Handle floats with
math.isclose; remember NaN is not equal to itself. - Collections compare by content; NumPy and pandas return elementwise boolean arrays.
- Avoid assuming
x != y != zmeans all unique; use a set size check.
Build smarter image and video workflows in your Python projects. Register for a free Cloudinary account to upload, transform, and deliver media at scale.