1

Using reserved keywords or built-in functions as variable/attribute names is commonly seen as bad practice. However, the SQLALchemy tutorial is full of exampled with attributes named id.

Straight from the tutorial

>>> class User(Base):
...     __tablename__ = "user_account"
...
...     id: Mapped[int] = mapped_column(primary_key=True)
...     name: Mapped[str] = mapped_column(String(30))
...     fullname: Mapped[Optional[str]]
...
...     addresses: Mapped[List["Address"]] = relationship(
...         back_populates="user", cascade="all, delete-orphan"
...     )
...
...     def __repr__(self) -> str:
...         return f"User(id={self.id!r}, name={self.name!r}, fullname={self.fullname!r})"

Why is it not recommended to use id_ instead, as recommended at least for keywords in PEP 8?

emilaz
  • 1,722
  • 1
  • 15
  • 31

1 Answers1

4

Firstly, id is not a keyword; if it was one, you would get a syntax error (try replacing id there with e.g. pass). It is a global identifier for a built-in function. And while it is a bad practice to clobber over the default identifiers defined by Python, note that id: Mapped[int] = mapped_column(primary_key=True) inside a class definition defines a static attribute of that class, not a global variable. The global function id is not the same as the static attribute User.id (or self.id, as it is used later) — there is no conflict there.

class Foo:
    id = 42

print(Foo.id)
# => 42
print(id)
# => <built-in function id>

However, as you correctly note:

id = "YOU SHOULDN'T DO THIS"
print(id)
# => YOU SHOULDN'T DO THIS
# (and not <built-in function id>)

Secondly, as to why id is used: SQLAlchemy maps classes to SQL tables with the snakecased class name, and attributes to SQL columns with the as-is attribute name (unless you specifically say id_: mapped_column('id', primary_key=True)), so id and id_ would be different columns in SQL.

id (as opposed to id_) is the conventional name of the primary key column in SQL (if there is a single-column primary key). Some people would name the column user_id, but many dislike having user_id in table called users, since it should be obvious what users.id, and so users.user_id is redundant; the form user_id is generally reserved for foreign keys. The SQLAlchemy examples merely follow this SQL convention.

Amadan
  • 191,408
  • 23
  • 240
  • 301