Which Of The Following Is Not A Keyword In Python

11 min read

You're staring at a multiple-choice question. The question reads: "Which of the following is not a keyword in Python?Maybe you're just curious. Even so, maybe it's a certification exam. Maybe it's a coding interview. " And you freeze.

Because print looks like a keyword. So does input. And range. And len.

Spoiler: none of those are keywords.

Let's clear this up once and for all.

What Are Python Keywords

Keywords are reserved words. The language itself claims them. You can't use them as variable names, function names, class names, or any other identifier. Try naming a variable for and Python will slap you with a SyntaxError before your code even runs.

There are 35 keywords in Python 3.On top of that, 12. Which means that's it. Thirty-five words that belong exclusively to the language.

The Difference Between Keywords and Built-ins

This is where almost everyone gets tripped up Most people skip this — try not to..

print is a built-in function. Practically speaking, len is a built-in function. Still, range is a built-in class. input is a built-in function. str, int, list, dict, set, tuple — all built-in types Most people skip this — try not to..

You can overwrite these. Not that you should. But you can.

print = "hello"  # Legal. Terrible idea. But legal.
len = 42         # Also legal. Also terrible.

Try that with if or while or def. You'll get a syntax error instantly. On top of that, that's the difference. Keywords are structural. Built-ins are just... available by default Less friction, more output..

Soft Keywords: The Newer Category

Python 3.10 introduced match and case for structural pattern matching. Even so, they're technically "soft keywords" — recognized in specific contexts but allowed as identifiers elsewhere. Practically speaking, python 3. 12 added type as a soft keyword for the new type statement.

You can still name a variable match outside a match statement. But don't. It's confusing.

Why Keywords Matter

You might wonder why this distinction even matters. Isn't it just trivia?

Not really.

Code That Won't Run

If you try to use a keyword as an identifier, your code fails at parse time. Not runtime. And parse time. Before a single line executes.

class = "my class"  # SyntaxError: invalid syntax
def = 5             # SyntaxError: invalid syntax

This catches typos early. Accidentally type retrun instead of return? Python won't stop you. But syntaxError. That's not a keyword — it's just a name. But type return outside a function? The keyword enforces structure.

Reading Other People's Code

When you see yield, you know a generator is involved. Practically speaking, when you see await, you know async code. On the flip side, keywords signal intent. Which means when you see nonlocal, you know nested scopes. They're signposts.

Avoiding Shadowing Bugs

Overwriting built-ins doesn't crash your program. It creates subtle bugs.

list = [1, 2, 3]
new_list = list("abc")  # TypeError: 'list' object is not callable

You just broke list() for the rest of that scope. Consider this: this happens in real codebases. Still, knowing what's a keyword vs. a built-in vs. a standard library name saves debugging hours.

The Complete List of Python Keywords

Here they are. In practice, all 35. Grouped by what they do Small thing, real impact..

Control Flow

if, elif, else — conditional branching
for, while — loops
break, continue — loop control
try, except, finally, else — exception handling (yes, else works on loops and try blocks too)
raise — throw an exception
assert — debugging checks
match, case — pattern matching (soft keywords)

Functions and Structure

def — define a function
return — exit a function with a value
yield — pause a generator
lambda — anonymous function
global, nonlocal — scope declarations
pass — placeholder statement

Classes

class — define a class
self is not a keyword. Here's the thing — it's convention. On top of that, you could use this or me or potato. But don't.

Imports and Modules

import, from, as — module handling

Boolean and None

True, False, None — singletons. Capitalized. Not true, false, null.

Logical Operators

and, or, not — boolean logic. Not &&, ||, !.

Membership and Identity

in, is — operators that happen to be keywords

Context Managers

with — resource management
as — also used here for aliasing the context manager result

Async

async, await — asynchronous programming

Other

del — delete references
type — soft keyword for type statements (3.12+)

That's the full list. Bookmark it. Or just run:

import keyword
print(keyword.kwlist)

Common Words That Look Like Keywords But Aren't

This is the section that answers your actual question. These words appear constantly in Python code. None are keywords That alone is useful..

Built-in Functions

print, len, range, input, open, sorted, reversed, enumerate, zip, map, filter, sum, max, min, abs, round, pow, divmod, isinstance, issubclass, hasattr, getattr, setattr, delattr, callable, iter, next, id, hash, help, vars, dir, locals, globals, eval, exec, compile, format, ascii, repr, chr, ord, hex, oct, bin, int, float, str, bool, list, tuple, set, frozenset, dict, bytes, bytearray, memoryview, object, type, super, property, classmethod, staticmethod, slice, complex

Wait — type appears in both lists now. Practically speaking, since 3. 12 it's a soft keyword and a built-in. Context determines which wins.

Built-in Exceptions

Exception, Error, ValueError, TypeError, KeyError, IndexError, AttributeError, ImportError, ModuleNotFoundError, FileNotFoundError, PermissionError, OSError, RuntimeError, StopIteration, StopAsyncIteration, KeyboardInterrupt, SystemExit, GeneratorExit, BaseException

Built-in Constants

Ellipsis, NotImplemented, __debug__

Built‑in Exceptions – the safety net of every Python program

When you deliberately raise an error or let an operation bubble up, you are usually working with one of the exception classes that live in the builtins module. They are not keywords, but they behave like reserved identifiers because they appear in almost every traceback you’ll ever read That alone is useful..

Category Typical subclasses When you’ll see them
Base BaseException The root of everything that can be caught with except. And
System‑level SystemExit, KeyboardInterrupt, GeneratorExit Triggered by sys. Worth adding: exit(), Ctrl‑C, or generator clean‑up. On the flip side,
Standard errors Exception, RuntimeError, SyntaxError, TypeError, ValueError The workhorses for ordinary error handling. That's why
Data‑structure errors KeyError, IndexError, AttributeError, TypeError (again) Occur when you try to access a missing key, out‑of‑range index, or an attribute that doesn’t exist.
Import failures ImportError, ModuleNotFoundError, ImportError (pre‑3.12) Happens when Python cannot locate a module or package. Worth adding:
IO problems FileNotFoundError, PermissionError, OSError Raised during file reads/writes or when the underlying OS reports an issue.
Network / concurrency TimeoutError, ConnectionError, BrokenPipeError Specific to sockets, HTTP requests, or other external resources.

This changes depending on context. Keep that in mind.

You can subclass any of these to create domain‑specific error types, e.g.:

class ValidationError(ValueError):
    """Raised when user input does not meet validation rules."""
    pass

Because they are ordinary classes, they can be caught, inspected, or re‑raised just like any other object.


Built‑in Constants – the immutable building blocks

Python ships with a handful of singleton objects that are globally available without any import. They are written with an initial capital letter, just like the boolean singletons The details matter here..

  • Ellipsis – represented by the literal .... It is used in slicing syntax and can also serve as a placeholder in custom indexing schemes.
  • NotImplemented – a signal to the interpreter that a method does not yet have an implementation; it should be overridden by a subclass.
  • __debug__ – evaluates to False when the interpreter is started with the -O (optimize) flag, allowing you to strip away debugging code in production builds.

These constants are immutable, hashable, and can be compared directly (if x is NotImplemented:), but they are not keywords; they are simply objects defined in the standard library.


Using Soft Keywords Wisely

Since Python 3.12, the parser treats certain identifiers as soft keywords only inside specific syntactic contexts (e.Even so, g. Also, , type in type‑annotation statements). Outside those contexts they behave exactly like regular identifiers, which means you can safely use them as variable names or function arguments when you are not annotating types Most people skip this — try not to..

def compute_type(x) -> None:   # 'type' is just a normal parameter name here
    pass

When you write a type hint, however, the parser switches modes:

def compute_type(x: int) -> int:  # now 'type' is a soft keyword, not allowed as a plain identifier
    ...

If you need a variable called type in a context where a type hint is expected, you can work around it by using a different name or by employing an annotation that does not involve the soft keyword.


Common Pitfalls and How to Avoid Them

  1. Accidentally shadowing a built‑in – Renaming a variable to list, dict, or str works, but it obscures the original function and can lead to subtle bugs.
    Tip: Keep built‑ins untouched; if you must use a similar name, limit its scope to a tiny inner block Most people skip this — try not to..

  2. Misreading soft keywords

  3. Misreading soft keywords – Because identifiers like match, case, or type are only treated as keywords in specific syntactic positions, it’s easy to assume they are reserved everywhere and avoid them unnecessarily, or conversely to use them where they actually permitted.
    **Check the language reference the the identifier is a soft keyword only when it appears after a colon in a type annotation, inside a match statement, or following case. In all other places you can safely name variables, functions, or classes with those identifiers Not complicated — just consistent. Nothing fancy..

    • Example: def case_insensitive_sort(seq): … is fine because case is not in a type‑annotation or pattern‑matching context.
    • Tip: When in doubt, run python -m ast on a snippet; the AST will show whether the token was parsed as a Name or as a Keyword.
  4. Over‑relying on Ellipsis as a “no‑op” placeholder – While ... is convenient for stubbing out functions (def foo(): ...) or marking slices (a[..., 0]), using it in production logic can be confusing because it evaluates to a singleton object that is truthy (bool(...) is True). If you later forget to replace the ellipsis with real code, the function will still return a value (None is implicit, but the ellipsis itself may be inspected elsewhere).

    • Tip: Reserve ... for genuine stubbing during development, and replace it with a pass or a raise NotImplementedError before merging to main.
    • Alternative: Use a custom sentinel object (_UNIMPLEMENTED = object()) and check if result is _UNIMPLEMENTED: to make the intent explicit.
  5. Assuming NotImplemented signals an error – Returning NotImplemented from a rich‑comparison method (__eq__, __lt__, etc.) tells Python to try the reflected operation on the other operand; it is not an exception. Mistakenly treating it as a failure and raising an error yourself can break fallback semantics and lead to surprising TypeErrors.

    • Tip: Only return NotImplemented when you genuinely cannot compare with the supplied type; otherwise return False or True as appropriate.
    • Example:
    class Money:
        def __eq__(self, other):
            if not isinstance(other, Money):
                return NotImplemented   # let other.__eq__ try
            return self.amount == other.amount and self.currency == other.currency
    
  6. Neglecting the effect of __debug__ on assertions – Since assert statements are removed when __debug__ is False (i.e., when running with -O), code that relies on assertions for runtime checks will silently skip those checks in optimized builds.

    • Tip: Use assertions only for conditions that should never happen in correct code (pre‑conditions, post‑conditions, invariants). For validation that must run in production, raise explicit exceptions instead.
    • Example of misuse:
    def withdraw(account, amount):
        assert amount > 0, "amount must be positive"   # disappears with -O
        ...
    

    Better:

    if amount <= 0:
        raise ValueError("amount must be positive")
    

Putting It All Together

Understanding the nuances of Python’s built‑in objects, the contextual nature of soft keywords, and the subtle behaviors of constants like Ellipsis, NotImplemented, and __debug__ empowers you to write code that is both expressive and solid. By reserving built‑in names for their intended purposes, using soft keywords only where they are syntactically meaningful, and treating placeholders and sentinel objects with clear intent, you avoid the most common sources of confusion and bugs Less friction, more output..


Conclusion
Python’s rich set of built‑ins and its evolving syntax give developers powerful tools, but they also demand careful attention to scope and context. By keeping built‑ins untouched, respecting the conditional nature of soft keywords, and using constants like Ellipsis, NotImplemented, and __debug__ exactly as they were designed, you harness the language’s strengths while minimizing surprises. Apply these practices consistently, and your code will remain readable, maintainable, and resilient across development and production environments Practical, not theoretical..

Just Went Up

Just Released

Worth Exploring Next

A Few Steps Further

Thank you for reading about Which Of The Following Is Not A Keyword In Python. We hope the information has been useful. Feel free to contact us if you have any questions. See you next time — don't forget to bookmark!
⌂ Back to Home