iTranslated by AI

The content below is an AI-generated translation. This is an experimental feature, and may contain errors. View original article
🐍

How to Return Constants in Python

に公開

Conclusion

Use Final + Static Analysis!

The Issue

"In Python, there's a way to annotate with Final and use static analysis!" "But Final is not verified at runtime!" "I want constants even at runtime!"

↓ Using Final prevents re-assignment, re-definition, and overwriting in Python's static analysis

↓ Since it is static analysis, it does not react at runtime

https://typing.readthedocs.io/en/latest/spec/qualifiers.html#syntax

https://mypy.readthedocs.io/en/stable/index.html

The Idea of Returning a Constant Function vs. Reality

Common Idea

"With this, it probably won't be overridden at runtime." "I've won; I'm off to the bath."

def hello() -> str:
    return "Hello, World!"

It Can Be Overwritten When Assigned to a Variable

Until I looked into it thoroughly, I thought using a function that returns a constant might be a good method, but apparently, there was a loophole.
"If someone assigns it to an object, it becomes a function object, so wouldn't it be updatable?" "Ugh."

def hello() -> str:
    return "Hello, World!"


if __name__ == "__main__":
    print(hello())  # Hello, World!

    h = hello()  # Hello, World!
    h = lambda: print("Overwritten!")

    h()  # Overwritten!

Referring to the Official Python Documentation

Looking closely at the official documentation, the Function itself is a C structure called PyFunctionObject. It seems like mischief is possible.

type PyFunctionObject
The C structure used for functions.

https://docs.python.org/3/c-api/function.html

Actually, the Function Itself Can Be Overwritten

For those who thought that if it's an object, even a function can be updated—you are correct.

def hello() -> str:
    return "Hello, World!"


def hello() -> str:
    return "Overwritten!"

if __name__ == "__main__":
    print(hello())  # Overwritten!

Summary

You can use Final by assigning a lambda function to a function-type object.
...However, my honest impression is that this is not much different from simply using Final[str].

from typing import Final, Callable

hello_world: Final[Callable[[], str]] = lambda: "Hello, World!"


if __name__ == "__main__":
    print(hello_world())  # Output: Hello, World!

typing Final use it --☆

Discussion