Skip to main content

Language Features

General​

1. Dictionary Access​

Accessing dictionary values: Always use [] syntax instead of .get(), unless you are using .get()’s optional argument to specify a default value.

script.python
value = data["key"]  # goodvalue = data.get("key")  # avoid (same behavior as above but doesn't error if key is missing)value = data.get("key", "default_value")  # good

There may be situations where you don't want to error if a key is missing but it's better to be explicit about what value is provided in the case that a key is missing. Allows for type of the value variable to be known no matter what just from reading.

2. Imports​

Prefer absolute imports over relative imports for accessing parent modules. Use relative imports when the path would be overly long or importing within the same package.

script.python
from app.file_name import xyz  # goodfrom ..file_name import xyz  # avoid when possible

Also never use wildcard imports to make it clear which names are present in the namespace and make it easier to trace where a method came from.

script.python
from file_name import specific_method, HelperClass # goodfrom file_name import * # bad

3. String Templating / f-strings​

Use f-strings instead of string concatenation.

script.python
f"Variable: {variable}" # good"Variable: " + str(variable) # bad (hard to read)

4. List Iterating​

This isn't that serious but preference for pythonic list iterating such as zip() and enumerate()

script.python
for i, fruit in enumerate(fruits):    print(f"Index {i}: {fruit}")for name, score in zip(names, scores):    print(f"{name}: {score}")

5. Default Mutable Arguments​

Never use default mutable arguments.

script.python
def add_to_list(num: int, lst: list[int] = []): # lst default value is [] which is mutable    lst.append(num)    return lstadd_to_list(5) # returns [5]add_to_list(6) # return [5, 6]

The default value keeps accumulating since it's mutable which is unexpected and can lead to difficult to debug bugs. Instead:

script.python
def add_to_list(num: int, lst: list[int] | None = None):    if not lst:        lst = []    lst.append(num)    return lst

Typing​

Typing is a smaller language feature for Python when compared to Typescript so instead of getting it's own typing page as Typescript did, it is a subsection of language features.

1. Type hinting​

Type hint all public functions and all FastAPI endpoints (inputs and outputs).

script.python
async def create_shapefile(self, latitude: float, longitude: float) -> str:
script.python
@router.get("/{uuid}/geojson", status_code=status.HTTP_200_OK, responses=GetGeojsonExampleResponses)async def get_shapefile_geojson(uuid: str, simplify: float | None = None) -> GeojsonConversionOut:

More details on typing FastAPI endpoint in FastAPI Specific page.

2. Typing collections​

Use prebuilt generics for collections (e.g., list[str], dict[str, int]), as opposed to outdated typed collections from the typing module.

script.python
from typing import Dictdef xyz() -> Dict[str, int]: # bad, comes from typing moduledef xyz() -> dict[str, int]: # good, uses generics

3. Optional Values​

Use | None for optional values (e.g., str | None) as opposed to Optional[str]

script.python
from typing import Optionalsimplify: Optional[float] = None # bad, slightly less readable and outdated syntaxsimplify: float | None = None # good

4. Any type​

Avoid Any unless it is required; add a short comment explaining why.

5. Fixed dictionary shape​

Use pydantic models when a dictionary object has a fixed shape.

script.python
from pydantic import BaseModelclass CreateSessionOut(BaseModel):    session_id: str    shapefiles: list[str]

6. Constrained string values​

Always use Literal for constrained string values.

script.python
from typing import LiteralStatus = Literal["pending", "active", "disabled"]

Copyright © 2026 Atheesh Thirumalairajan