| # Overview |
| |
| In order to fulfill its ambitious goal of bringing back the joy to writing classes, it gives you a class decorator and a way to declaratively define the attributes on that class: |
| |
| ```{include} ../README.md |
| :start-after: 'code-begin -->' |
| :end-before: '## Project Information' |
| ``` |
| |
| |
| ## Philosophy |
| |
| **It's about regular classes.** |
| |
| : *attrs* is for creating well-behaved classes with a type, attributes, methods, and everything that comes with a class. |
| It can be used for data-only containers like `namedtuple`s or `types.SimpleNamespace` but they're just a sub-genre of what *attrs* is good for. |
| |
| |
| **The class belongs to the users.** |
| |
| : You define a class and *attrs* adds static methods to that class based on the attributes you declare. |
| The end. |
| It doesn't add metaclasses. |
| It doesn't add classes you've never heard of to your inheritance tree. |
| An *attrs* class in runtime is indistinguishable from a regular class: because it *is* a regular class with a few boilerplate-y methods attached. |
| |
| |
| **Be light on API impact.** |
| |
| : As convenient as it seems at first, *attrs* will *not* tack on any methods to your classes except for the {term}`dunder ones <dunder methods>`. |
| Hence all the useful [tools](helpers) that come with *attrs* live in functions that operate on top of instances. |
| Since they take an *attrs* instance as their first argument, you can attach them to your classes with one line of code. |
| |
| |
| **Performance matters.** |
| |
| : *attrs* runtime impact is very close to zero because all the work is done when the class is defined. |
| Once you're instantiating it, *attrs* is out of the picture completely. |
| |
| |
| **No surprises.** |
| |
| : *attrs* creates classes that arguably work the way a Python beginner would reasonably expect them to work. |
| It doesn't try to guess what you mean because explicit is better than implicit. |
| It doesn't try to be clever because software shouldn't be clever. |
| |
| Check out {doc}`how-does-it-work` if you'd like to know how it achieves all of the above. |
| |
| |
| ## What *attrs* Is Not |
| |
| *attrs* does *not* invent some kind of magic system that pulls classes out of its hat using meta classes, runtime introspection, and shaky interdependencies. |
| |
| All *attrs* does is: |
| |
| 1. Take your declaration, |
| 2. write {term}`dunder methods` based on that information, |
| 3. and attach them to your class. |
| |
| It does *nothing* dynamic at runtime, hence zero runtime overhead. |
| It's still *your* class. |
| Do with it as you please. |