{"id":13419637,"url":"https://github.com/python-attrs/attrs","last_synced_at":"2025-05-12T20:46:18.755Z","repository":{"id":26467388,"uuid":"29918975","full_name":"python-attrs/attrs","owner":"python-attrs","description":"Python Classes Without Boilerplate","archived":false,"fork":false,"pushed_at":"2025-05-01T11:10:30.000Z","size":4057,"stargazers_count":5473,"open_issues_count":141,"forks_count":386,"subscribers_count":59,"default_branch":"main","last_synced_at":"2025-05-05T16:06:27.608Z","etag":null,"topics":["attributes","boilerplate","classes","oop","python"],"latest_commit_sha":null,"homepage":"https://www.attrs.org/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/python-attrs.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":".github/CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":".github/CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":"CITATION.cff","codeowners":null,"security":".github/SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":"hynek","tidelift":"pypi/attrs"}},"created_at":"2015-01-27T15:01:01.000Z","updated_at":"2025-05-05T02:34:36.000Z","dependencies_parsed_at":"2024-04-07T00:28:42.291Z","dependency_job_id":"a7bd42bd-8e77-4e79-b155-54b330173149","html_url":"https://github.com/python-attrs/attrs","commit_stats":{"total_commits":1599,"total_committers":169,"mean_commits":9.461538461538462,"dds":"0.23389618511569732","last_synced_commit":"19518e74f0083cdb2d6b261f898b5acfdbe50988"},"previous_names":["hynek/attrs"],"tags_count":36,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/python-attrs%2Fattrs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/python-attrs%2Fattrs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/python-attrs%2Fattrs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/python-attrs%2Fattrs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/python-attrs","download_url":"https://codeload.github.com/python-attrs/attrs/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252596427,"owners_count":21773846,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["attributes","boilerplate","classes","oop","python"],"created_at":"2024-07-30T22:01:18.757Z","updated_at":"2025-05-12T20:46:18.738Z","avatar_url":"https://github.com/python-attrs.png","language":"Python","readme":"\u003cp align=\"center\"\u003e\n   \u003ca href=\"https://www.attrs.org/\"\u003e\n      \u003cpicture\u003e\n         \u003csource srcset=\"https://raw.githubusercontent.com/python-attrs/attrs/main/docs/_static/attrs_logo_white.svg\" media=\"(prefers-color-scheme: dark)\"\u003e\n         \u003cimg src=\"https://raw.githubusercontent.com/python-attrs/attrs/main/docs/_static/attrs_logo.svg\" width=\"35%\" alt=\"attrs\" /\u003e\n      \u003c/picture\u003e\n   \u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n   \u003ca href=\"https://www.attrs.org/en/stable/\"\u003e\u003cimg src=\"https://img.shields.io/badge/Docs-RTD-black\" alt=\"Documentation\" /\u003e\u003c/a\u003e\n   \u003ca href=\"https://bestpractices.coreinfrastructure.org/projects/6482\"\u003e\u003cimg src=\"https://bestpractices.coreinfrastructure.org/projects/6482/badge\"\u003e\u003c/a\u003e\n   \u003ca href=\"https://pypi.org/project/attrs/\"\u003e\u003cimg src=\"https://img.shields.io/pypi/v/attrs\" /\u003e\u003c/a\u003e\n   \u003ca href=\"https://pepy.tech/project/attrs\"\u003e\u003cimg src=\"https://static.pepy.tech/personalized-badge/attrs?period=month\u0026units=international_system\u0026left_color=grey\u0026right_color=blue\u0026left_text=Downloads%20/%20Month\" alt=\"Downloads per month\" /\u003e\u003c/a\u003e\n   \u003ca href=\"https://zenodo.org/badge/latestdoi/29918975\"\u003e\u003cimg src=\"https://zenodo.org/badge/29918975.svg\" alt=\"DOI\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003c!-- teaser-begin --\u003e\n\n*attrs* is the Python package that will bring back the **joy** of **writing classes** by relieving you from the drudgery of implementing object protocols (aka [dunder methods](https://www.attrs.org/en/latest/glossary.html#term-dunder-methods)).\n[Trusted by NASA](https://docs.github.com/en/account-and-profile/setting-up-and-managing-your-github-profile/customizing-your-profile/personalizing-your-profile#list-of-qualifying-repositories-for-mars-2020-helicopter-contributor-achievement) for Mars missions since 2020!\n\nIts main goal is to help you to write **concise** and **correct** software without slowing down your code.\n\n\n## Sponsors\n\n*attrs* would not be possible without our [amazing sponsors](https://github.com/sponsors/hynek).\nEspecially those generously supporting us at the *The Organization* tier and higher:\n\n\u003c!-- sponsor-break-begin --\u003e\n\n\u003cp align=\"center\"\u003e\n\n\u003c!-- [[[cog\nimport pathlib, tomllib\n\nfor sponsor in tomllib.loads(pathlib.Path(\"pyproject.toml\").read_text())[\"tool\"][\"sponcon\"][\"sponsors\"]:\n      print(f'\u003ca href=\"{sponsor[\"url\"]}\"\u003e\u003cimg title=\"{sponsor[\"title\"]}\" src=\"docs/_static/sponsors/{sponsor[\"img\"]}\" width=\"190\" /\u003e\u003c/a\u003e')\n]]] --\u003e\n\u003ca href=\"https://www.variomedia.de/\"\u003e\u003cimg title=\"Variomedia AG\" src=\"docs/_static/sponsors/Variomedia.svg\" width=\"190\" /\u003e\u003c/a\u003e\n\u003ca href=\"https://tidelift.com/?utm_source=lifter\u0026utm_medium=referral\u0026utm_campaign=hynek\"\u003e\u003cimg title=\"Tidelift\" src=\"docs/_static/sponsors/Tidelift.svg\" width=\"190\" /\u003e\u003c/a\u003e\n\u003ca href=\"https://klaviyo.com/\"\u003e\u003cimg title=\"Klaviyo\" src=\"docs/_static/sponsors/Klaviyo.svg\" width=\"190\" /\u003e\u003c/a\u003e\n\u003ca href=\"https://privacy-solutions.org/\"\u003e\u003cimg title=\"Privacy Solutions\" src=\"docs/_static/sponsors/Privacy-Solutions.svg\" width=\"190\" /\u003e\u003c/a\u003e\n\u003ca href=\"https://www.emsys-renewables.com/\"\u003e\u003cimg title=\"emsys renewables\" src=\"docs/_static/sponsors/emsys-renewables.svg\" width=\"190\" /\u003e\u003c/a\u003e\n\u003ca href=\"https://filepreviews.io/\"\u003e\u003cimg title=\"FilePreviews\" src=\"docs/_static/sponsors/FilePreviews.svg\" width=\"190\" /\u003e\u003c/a\u003e\n\u003ca href=\"https://polar.sh/\"\u003e\u003cimg title=\"Polar\" src=\"docs/_static/sponsors/Polar.svg\" width=\"190\" /\u003e\u003c/a\u003e\n\u003c!-- [[[end]]] --\u003e\n\n\u003c/p\u003e\n\n\u003c!-- sponsor-break-end --\u003e\n\n\u003cp align=\"center\"\u003e\n   \u003cstrong\u003ePlease consider \u003ca href=\"https://github.com/sponsors/hynek\"\u003ejoining them\u003c/a\u003e to help make \u003cem\u003eattrs\u003c/em\u003e’s maintenance more sustainable!\u003c/strong\u003e\n\u003c/p\u003e\n\n\u003c!-- teaser-end --\u003e\n\n## Example\n\n*attrs* gives you a class decorator and a way to declaratively define the attributes on that class:\n\n\u003c!-- code-begin --\u003e\n\n```pycon\n\u003e\u003e\u003e from attrs import asdict, define, make_class, Factory\n\n\u003e\u003e\u003e @define\n... class SomeClass:\n...     a_number: int = 42\n...     list_of_numbers: list[int] = Factory(list)\n...\n...     def hard_math(self, another_number):\n...         return self.a_number + sum(self.list_of_numbers) * another_number\n\n\n\u003e\u003e\u003e sc = SomeClass(1, [1, 2, 3])\n\u003e\u003e\u003e sc\nSomeClass(a_number=1, list_of_numbers=[1, 2, 3])\n\n\u003e\u003e\u003e sc.hard_math(3)\n19\n\u003e\u003e\u003e sc == SomeClass(1, [1, 2, 3])\nTrue\n\u003e\u003e\u003e sc != SomeClass(2, [3, 2, 1])\nTrue\n\n\u003e\u003e\u003e asdict(sc)\n{'a_number': 1, 'list_of_numbers': [1, 2, 3]}\n\n\u003e\u003e\u003e SomeClass()\nSomeClass(a_number=42, list_of_numbers=[])\n\n\u003e\u003e\u003e C = make_class(\"C\", [\"a\", \"b\"])\n\u003e\u003e\u003e C(\"foo\", \"bar\")\nC(a='foo', b='bar')\n```\n\nAfter *declaring* your attributes, *attrs* gives you:\n\n- a concise and explicit overview of the class's attributes,\n- a nice human-readable `__repr__`,\n- equality-checking methods,\n- an initializer,\n- and much more,\n\n*without* writing dull boilerplate code again and again and *without* runtime performance penalties.\n\n---\n\nThis example uses *attrs*'s modern APIs that have been introduced in version 20.1.0, and the *attrs* package import name that has been added in version 21.3.0.\nThe classic APIs (`@attr.s`, `attr.ib`, plus their serious-business aliases) and the `attr` package import name will remain **indefinitely**.\n\nCheck out [*On The Core API Names*](https://www.attrs.org/en/latest/names.html) for an in-depth explanation!\n\n\n### Hate Type Annotations!?\n\nNo problem!\nTypes are entirely **optional** with *attrs*.\nSimply assign `attrs.field()` to the attributes instead of annotating them with types:\n\n```python\nfrom attrs import define, field\n\n@define\nclass SomeClass:\n    a_number = field(default=42)\n    list_of_numbers = field(factory=list)\n```\n\n\n## Data Classes\n\nOn the tin, *attrs* might remind you of `dataclasses` (and indeed, `dataclasses` [are a descendant](https://hynek.me/articles/import-attrs/) of *attrs*).\nIn practice it does a lot more and is more flexible.\nFor instance, it allows you to define [special handling of NumPy arrays for equality checks](https://www.attrs.org/en/stable/comparison.html#customization), allows more ways to [plug into the initialization process](https://www.attrs.org/en/stable/init.html#hooking-yourself-into-initialization), has a replacement for `__init_subclass__`, and allows for stepping through the generated methods using a debugger.\n\nFor more details, please refer to our [comparison page](https://www.attrs.org/en/stable/why.html#data-classes), but generally speaking, we are more likely to commit crimes against nature to make things work that one would expect to work, but that are quite complicated in practice.\n\n\n## Project Information\n\n- [**Changelog**](https://www.attrs.org/en/stable/changelog.html)\n- [**Documentation**](https://www.attrs.org/)\n- [**PyPI**](https://pypi.org/project/attrs/)\n- [**Source Code**](https://github.com/python-attrs/attrs)\n- [**Contributing**](https://github.com/python-attrs/attrs/blob/main/.github/CONTRIBUTING.md)\n- [**Third-party Extensions**](https://github.com/python-attrs/attrs/wiki/Extensions-to-attrs)\n- **Get Help**: use the `python-attrs` tag on [Stack Overflow](https://stackoverflow.com/questions/tagged/python-attrs)\n\n\n### *attrs* for Enterprise\n\nAvailable as part of the [Tidelift Subscription](https://tidelift.com/?utm_source=lifter\u0026utm_medium=referral\u0026utm_campaign=hynek).\n\nThe maintainers of *attrs* and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source packages you use to build your applications.\nSave time, reduce risk, and improve code health, while paying the maintainers of the exact packages you use.\n","funding_links":["https://github.com/sponsors/hynek","https://tidelift.com/funding/github/pypi/attrs","https://tidelift.com/?utm_source=lifter\u0026utm_medium=referral\u0026utm_campaign=hynek","https://polar.sh/"],"categories":["Python","Built-in Classes Enhancement","Containers \u0026 Language Extentions \u0026 Linting","内置类增强功能","Miscellaneous","General Utilities","内置类的增强版实现","Built-in Classes Enhancement [🔝](#readme)","资源列表","Awesome Python","Model, Schema"],"sub_categories":["For Python","内置类的增强版实现","Built-in Classes Enhancement"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpython-attrs%2Fattrs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpython-attrs%2Fattrs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpython-attrs%2Fattrs/lists"}