[](https://www.python.org/)
[](https://choosealicense.com/licenses/mit/)
[](https://coveralls.io/github/yazernin10x/constify?branch=main)
[](https://github.com/yazernin10x/constify/actions/workflows/test.yml)
[](https://tox.wiki/en/latest/config.html)
[](https://github.com/astral-sh/ruff)
[](https://mypy-lang.org/)
# Constify
The `constify` library provides the `freezeparams` decorator to make mutable default values and arguments passed to functions immutable.
## Why use the `freezeparams` decorator ?
[[1]](#sources) The default value of a parameter is evaluated only once, which can lead to unexpected behavior if the value is a mutable object, such as a list or a dictionary. For example, the following function accumulates arguments across calls:
### Example
```python
def f(a, L=[]):
L.append(a)
return L
print(f(1)) # [1]
print(f(2)) # [1, 2]
print(f(3)) # [1, 2, 3]
```
To prevent this default value from being shared, the function can be rewritten as follows:
```python
def f(a, L=None):
if L is None:
L = []
L.append(a)
return L
```
This solution is effective, but with multiple mutable default values, it requires many checks. The `freezeparams` decorator simplifies the use of mutable objects as default values and arguments.
## Installation
```bash
pip install constify
```
## Usage
```python
from constify import freezeparams
@freezeparams
def f(a, L=[]):
L.append(a)
return L
# Default value (list) remains unchanged
print("f(1) =>", f(1)) # [1]
print("f(2) =>", f(2)) # [2]
print("f(3) =>", f(3)) # [3]
print("-" * 25) # just a separator
# Passed list remains intact
x = [1, 2]
print("x =", x) # [1, 2]
print(f"f(3, {x}) =>", f(3, x)) # [1, 2, 3]
print(f"f(4, {x}) =>", f(4, x)) # [1, 2, 4]
print("x =", x) # [1, 2]
```
**You can comment out the decorator and run the code again to see the difference.**
*Simple and effective!*
## Sources
[1] https://docs.python.org/3.13/tutorial/controlflow.html#default-argument-values
Raw data
{
"_id": null,
"home_page": null,
"name": "constify",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.9",
"maintainer_email": null,
"keywords": "mutable, immutable, decorator, default values, mutable arguments",
"author": null,
"author_email": "YARO Ali <ali.yaro@hotmail.com>",
"download_url": "https://files.pythonhosted.org/packages/4d/64/866d865699e866043177d4b09b99d13b8f3d208b958d213e0d2a614c7517/constify-0.1.0.tar.gz",
"platform": null,
"description": "[](https://www.python.org/)\r\n[](https://choosealicense.com/licenses/mit/)\r\n[](https://coveralls.io/github/yazernin10x/constify?branch=main)\r\n[](https://github.com/yazernin10x/constify/actions/workflows/test.yml)\r\n[](https://tox.wiki/en/latest/config.html)\r\n[](https://github.com/astral-sh/ruff)\r\n[](https://mypy-lang.org/)\r\n\r\n# Constify\r\n\r\nThe `constify` library provides the `freezeparams` decorator to make mutable default values and arguments passed to functions immutable.\r\n\r\n## Why use the `freezeparams` decorator ?\r\n\r\n[[1]](#sources) The default value of a parameter is evaluated only once, which can lead to unexpected behavior if the value is a mutable object, such as a list or a dictionary. For example, the following function accumulates arguments across calls:\r\n\r\n### Example\r\n```python\r\ndef f(a, L=[]):\r\n L.append(a)\r\n return L\r\n\r\nprint(f(1)) # [1]\r\nprint(f(2)) # [1, 2]\r\nprint(f(3)) # [1, 2, 3]\r\n```\r\n\r\nTo prevent this default value from being shared, the function can be rewritten as follows:\r\n\r\n```python\r\ndef f(a, L=None):\r\n if L is None:\r\n L = []\r\n L.append(a)\r\n return L\r\n```\r\n\r\nThis solution is effective, but with multiple mutable default values, it requires many checks. The `freezeparams` decorator simplifies the use of mutable objects as default values and arguments.\r\n\r\n## Installation\r\n\r\n```bash\r\npip install constify\r\n```\r\n\r\n## Usage\r\n\r\n```python\r\nfrom constify import freezeparams\r\n\r\n@freezeparams\r\ndef f(a, L=[]):\r\n L.append(a)\r\n return L\r\n\r\n# Default value (list) remains unchanged\r\nprint(\"f(1) =>\", f(1)) # [1]\r\nprint(\"f(2) =>\", f(2)) # [2]\r\nprint(\"f(3) =>\", f(3)) # [3]\r\n\r\nprint(\"-\" * 25) # just a separator\r\n\r\n# Passed list remains intact\r\nx = [1, 2]\r\nprint(\"x =\", x) # [1, 2]\r\nprint(f\"f(3, {x}) =>\", f(3, x)) # [1, 2, 3]\r\nprint(f\"f(4, {x}) =>\", f(4, x)) # [1, 2, 4]\r\nprint(\"x =\", x) # [1, 2]\r\n```\r\n**You can comment out the decorator and run the code again to see the difference.**\r\n\r\n*Simple and effective!*\r\n\r\n## Sources\r\n\r\n[1] https://docs.python.org/3.13/tutorial/controlflow.html#default-argument-values\r\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Makes functions parameters immutable",
"version": "0.1.0",
"project_urls": {
"Issue tracker": "https://github.com/yazernin10x/constify/issues",
"Repository": "https://github.com/yazernin10x/constify"
},
"split_keywords": [
"mutable",
" immutable",
" decorator",
" default values",
" mutable arguments"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "abde5a2017f3b009755754952f19040736a7c06170008af98346587a42235715",
"md5": "cca9525bbf89820e385728549f00b5a6",
"sha256": "caaa0c7b5e8fec621df45cf1eb7eb9c2fba89cb4b64067fb76f95ebda4393e9e"
},
"downloads": -1,
"filename": "constify-0.1.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "cca9525bbf89820e385728549f00b5a6",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.9",
"size": 4758,
"upload_time": "2025-01-13T18:13:18",
"upload_time_iso_8601": "2025-01-13T18:13:18.201729Z",
"url": "https://files.pythonhosted.org/packages/ab/de/5a2017f3b009755754952f19040736a7c06170008af98346587a42235715/constify-0.1.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "4d64866d865699e866043177d4b09b99d13b8f3d208b958d213e0d2a614c7517",
"md5": "0d497e4e3b28eafeaaf19b7422f9a44f",
"sha256": "c55aa073ab6cd8ba8bb88245f25ce0e130897233f3184073638c544ebea20c33"
},
"downloads": -1,
"filename": "constify-0.1.0.tar.gz",
"has_sig": false,
"md5_digest": "0d497e4e3b28eafeaaf19b7422f9a44f",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.9",
"size": 6296,
"upload_time": "2025-01-13T18:13:20",
"upload_time_iso_8601": "2025-01-13T18:13:20.724111Z",
"url": "https://files.pythonhosted.org/packages/4d/64/866d865699e866043177d4b09b99d13b8f3d208b958d213e0d2a614c7517/constify-0.1.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-01-13 18:13:20",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "yazernin10x",
"github_project": "constify",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "constify"
}