72 lines
3.0 KiB
Markdown
72 lines
3.0 KiB
Markdown
# 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: '### Hate Type Annotations!?'
|
||
```
|
||
|
||
|
||
## 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.
|
||
|
||
---
|
||
|
||
*attrs* also is *not* a fully-fledged serialization library.
|
||
While it comes with features like converters and validators, it is meant to be a kit for building classes that you would write yourself – but with less boilerplate.
|
||
If you look for powerful-yet-unintrusive serialization and validation for your *attrs* classes, have a look at our sibling project [*cattrs*](https://catt.rs/) or our [third-party extensions](https://github.com/python-attrs/attrs/wiki/Extensions-to-attrs).
|
||
|
||
This separation of creating classes and serializing them is a conscious design decision.
|
||
We don't think that your business model and your serialization format should be coupled.
|