4.7 Identifiers
The naming rules for Python identifiers, PEP 8 naming conventions, valid vs invalid identifier examples, and why reserved words can't be used as names.
What Are Identifiers?
What Is It?
Identifiers are the names you give to variables, functions, classes, and modules.
Python stores values in objects and uses identifiers as readable references to those objects. An identifier is not the value itself, and assigning a new value to a name does not change the old object.
What Are the Rules?
- It must start with a letter or underscore (not a digit)
- It may contain letters, digits, and underscores after that
- Identifiers are case-sensitive
- It cannot be a keyword
Naming Conventions
See 4.16 Coding Standards (PEP 8) for the full naming table — snake_case for variables/functions, PascalCase for classes, UPPER_SNAKE_CASE for constants.
| Identifier kind | Recommended style | Example |
|---|---|---|
| Variable or function | snake_case | retry_count, load_config() |
| Class | PascalCase | DeploymentConfig |
| Constant | UPPER_SNAKE_CASE | DEFAULT_TIMEOUT |
| Internal implementation detail | One leading underscore | _parse_labels() |
| Module or package | Short lowercase name | inventory.py |
A leading underscore is a naming convention, not a security boundary. It signals that an identifier is intended for internal use. Python’s name-mangling behavior for __name inside a class is separate from this convention.
Valid vs Invalid Identifiers
How Is It Used?
>>> "valid_name".isidentifier()
True
>>> "2invalid".isidentifier() # cannot start with a digit
False
>>> "my-var".isidentifier() # hyphens are not allowed
False
Unicode letters can also be valid in identifiers, but ASCII names are usually easier for teams to search, type, review, and operate across shells and CI systems:
service_name = "api"
π = 3.14159
print(service_name, π)
For production automation, prefer descriptive ASCII identifiers unless the project has a deliberate convention for Unicode names.
How Python Validates an Identifier
Python checks the first character, the remaining characters, and whether the name is reserved. A valid-looking name can still fail the final check if it is a keyword.
import keyword
def can_be_identifier(candidate: str) -> bool:
return candidate.isidentifier() and not keyword.iskeyword(candidate)
for candidate in ("pod_name", "9pods", "class", "service-name"):
print(candidate, can_be_identifier(candidate))
Expected output:
pod_name True
9pods False
class False
service-name False
Reserved Words
The 35 keywords from 4.6 Keywords cannot be used as identifiers, even though they otherwise look like valid names — Python’s parser treats them as fixed syntax rather than user-defined names.
Built-in names are different from keywords. Names such as list, type, and id are valid identifiers, but reusing them hides the built-in and can cause a later failure:
list = ["api", "worker"]
print(list("abc")) # TypeError: 'list' object is not callable
Use names such as services or service_names instead. A linter can catch many shadowing problems before they reach CI.
Scope and Rebinding
An identifier can refer to different objects in different scopes. A local assignment normally does not change a global name with the same spelling:
environment = "production"
def deploy():
environment = "staging"
return environment
print(deploy()) # staging
print(environment) # production
The function’s environment is a local identifier. Use global or nonlocal only when rebinding an outer name is intentional; passing values and returning results is usually easier to test.
Practical DevOps Example
Clear identifiers make automation scripts easier to review and reduce mistakes when several configuration values have similar meanings:
import os
DEFAULT_REGION = "us-east-1"
def deployment_target() -> tuple[str, str]:
region = os.getenv("AWS_REGION", DEFAULT_REGION)
cluster_name = os.environ["EKS_CLUSTER_NAME"]
return cluster_name, region
cluster_name, region = deployment_target()
print(f"Deploying to {cluster_name} in {region}")
DEFAULT_REGION communicates a constant, while cluster_name and region communicate values that can change. Avoid vague names such as x, data, or value when the script performs infrastructure operations.
Quick Interview Answer
“An identifier must start with a letter or underscore, contain only letters/digits/underscores after that, and can’t be a keyword. Identifiers are case-sensitive —
totalandTotalare different names. Usestr.isidentifier()to check programmatically, andkeyword.iskeyword()to check whether a valid-looking name is actually reserved.”
Troubleshooting Checklist
When Python reports an invalid identifier:
- Check that the first character is not a digit.
- Replace hyphens, spaces, and punctuation with underscores.
- Check the spelling against
keyword.kwlistif the name looks like Python syntax. - Look for invisible or non-ASCII characters copied from documentation.
- Check for accidental built-in shadowing such as
list = ...orid = .... - Run
python -m py_compile your_script.pyto catch parsing errors before executing the script.
Interview Follow-up Questions
- What is the difference between an identifier and a variable in Python?
- Why are
totalandTotaldifferent identifiers? - How do
str.isidentifier()andkeyword.iskeyword()differ? - Is
_nameprivate in Python? - What problem is caused by assigning a value to
listorid? - How does local scope affect an identifier with the same name as a global variable?
Common Mistakes
- Starting an identifier with a digit (
2invalid) — always aSyntaxError. - Using a hyphen instead of an underscore (
my-var) — Python parses the hyphen as a minus operator, not part of the name. - Assuming identifiers are case-insensitive, then being confused why
Usernameandusernameare treated as two separate variables. - Confusing a valid identifier with a good name —
datamay be legal, butpod_metadatais more useful to the next engineer. - Treating a leading underscore as access control — it communicates intent but does not prevent access from other code.
Add More Questions to This Guide
Know a question that should be here? Share it and help the community!
Open Google Form