Why should you use attrs more
Introduction
Python's attrs library is a game-changer for developers looking to simplify class creation and reduce boilerplate code. This libray is even trusted by NASA.
Created by Hynek Schlawack in 2015, attrs has quickly become a favorite tool among Python developers for its ability to automatically generate special methods and provide a clean, declarative way to define classes.
dataclasses is a kind of subset of attrs.
Why attrs is useful:
- Reduces boilerplate code
- Improves code readability and maintainability
- Provides powerful features for data validation and conversion
- Enhances performance through optimized implementations
2. Getting Started with attrs
Installation:
To get started with attrs, you can install it using pip:
pip install attrs
Basic usage:
Here's a simple example of how to use attrs to define a class:
import attr @attr.s class Person: name = attr.ib() age = attr.ib() # Creating an instance person = Person("Alice", 30) print(person) # Person(name='Alice', age=30)
3. Core Features of attrs
a. Automatic method generation:
attrs automatically generates init, repr, and eq methods for your classes:
@attr.s class Book: title = attr.ib() author = attr.ib() year = attr.ib() book1 = Book("1984", "George Orwell", 1949) book2 = Book("1984", "George Orwell", 1949) print(book1) # Book(title='1984', author='George Orwell', year=1949) print(book1 == book2) # True
b. Attribute definition with types and default values:
import attr from typing import List @attr.s class Library: name = attr.ib(type=str) books = attr.ib(type=List[str], default=attr.Factory(list)) capacity = attr.ib(type=int, default=1000) library = Library("City Library") print(library) # Library(name='City Library', books=[], capacity=1000)
c. Validators and converters:
import attr def must_be_positive(instance, attribute, value): if value <= 0: raise ValueError("Value must be positive") @attr.s class Product: name = attr.ib() price = attr.ib(converter=float, validator=[attr.validators.instance_of(float), must_be_positive]) product = Product("Book", "29.99") print(product) # Product(name='Book', price=29.99) try: Product("Invalid", -10) except ValueError as e: print(e) # Value must be positive
4. Advanced Usage
a. Customizing attribute behavior:
import attr @attr.s class User: username = attr.ib() _password = attr.ib(repr=False) # Exclude from repr @property def password(self): return self._password @password.setter def password(self, value): self._password = hash(value) # Simple hashing for demonstration user = User("alice", "secret123") print(user) # User(username='alice')
b. Frozen instances and slots:
@attr.s(frozen=True) # slots=True is the default class Point: x = attr.ib() y = attr.ib() point = Point(1, 2) try: point.x = 3 # This will raise an AttributeError except AttributeError as e: print(e) # can't set attribute
c. Factory functions and post-init processing:
import attr import uuid @attr.s class Order: id = attr.ib(factory=uuid.uuid4) items = attr.ib(factory=list) total = attr.ib(init=False) def __attrs_post_init__(self): self.total = sum(item.price for item in self.items) @attr.s class Item: name = attr.ib() price = attr.ib(type=float) order = Order(items=[Item("Book", 10.99), Item("Pen", 1.99)]) print(order) # Order(id=UUID('...'), items=[Item(name='Book', price=10.99), Item(name='Pen', price=1.99)], total=12.98)
5. Best Practices and Common Pitfalls
Best Practices:
- Use type annotations for better code readability and IDE support
- Leverage validators for data integrity
- Use frozen classes for immutable objects
- Take advantage of automatic method generation to reduce code duplication
Common Pitfalls:
- Forgetting to use @attr.s decorator on the class
- Overusing complex validators that could be separate methods
- Not considering the performance impact of extensive use of factory functions
6. attrs vs Other Libraries
Library | Features | Performance | Community |
---|---|---|---|
attrs | Automatic method generation, attribute definition with types and default values, validators and converters | Better performance than manual code | Active community |
pydantic | Data validation and settings management, automatic method generation, attribute definition with types and default values, validators and converters | Good performance | Active community |
dataclasses | Built into Python 3.7+, making them more accessible | Tied to the Python version | Built-in Python library |
attrs and dataclasses are faster than pydantic1.
Comparison with dataclasses:
- attrs is more feature-rich and flexible
- dataclasses are built into Python 3.7+, making them more accessible
- attrs has better performance in most cases
- dataclasses are tied to the Python version, while attrs as an external library can be used with any Python version.
Comparison with pydantic:
- pydantic is focused on data validation and settings management
- attrs is more general-purpose and integrates better with existing codebases
- pydantic has built-in JSON serialization, while attrs requires additional libraries
When to choose attrs:
- For complex class hierarchies with custom behaviors
- When you need fine-grained control over attribute definitions
- For projects that require Python 2 compatibility (though less relevant now)
7. Performance and Real-world Applications
Performance:
attrs generally offers better performance than manually written classes or other libraries due to its optimized implementations.
Real-world example:
from attr import define, Factory from typing import List, Optional @define class Customer: id: int name: str email: str orders: List['Order'] = Factory(list) @define class Order: id: int customer_id: int total: float items: List['OrderItem'] = Factory(list) @define class OrderItem: id: int order_id: int product_id: int quantity: int price: float @define class Product: id: int name: str price: float description: Optional[str] = None # Usage customer = Customer(1, "Alice", "alice@example.com") product = Product(1, "Book", 29.99, "A great book") order_item = OrderItem(1, 1, 1, 2, product.price) order = Order(1, customer.id, 59.98, [order_item]) customer.orders.append(order) print(customer)
8. Conclusion and Call to Action
attrs is a powerful library that simplifies Python class definitions while providing robust features for data validation and manipulation. Its ability to reduce boilerplate code, improve readability, and enhance performance makes it an invaluable tool for Python developers.
Community resources:
- GitHub repository: https://github.com/python-attrs/attrs
- Documentation: https://www.attrs.org/
- PyPI page: https://pypi.org/project/attrs/
Try attrs in your next project and experience its benefits firsthand. Share your experiences with the community and contribute to its ongoing development. Happy coding!
-
https://stefan.sofa-rockers.org/2020/05/29/attrs-dataclasses-pydantic/ ↩
The above is the detailed content of Why should you use attrs more. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undress AI Tool
Undress images for free

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

ArtGPT
AI image generator for creative art from text prompts.

Stock Market GPT
AI powered investment research for smarter decisions

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Run pipinstall-rrequirements.txt to install the dependency package. It is recommended to create and activate the virtual environment first to avoid conflicts, ensure that the file path is correct and that the pip has been updated, and use options such as --no-deps or --user to adjust the installation behavior if necessary.

This tutorial details how to efficiently merge the PEFT LoRA adapter with the base model to generate a completely independent model. The article points out that it is wrong to directly use transformers.AutoModel to load the adapter and manually merge the weights, and provides the correct process to use the merge_and_unload method in the peft library. In addition, the tutorial also emphasizes the importance of dealing with word segmenters and discusses PEFT version compatibility issues and solutions.

Python is a simple and powerful testing tool in Python. After installation, test files are automatically discovered according to naming rules. Write a function starting with test_ for assertion testing, use @pytest.fixture to create reusable test data, verify exceptions through pytest.raises, supports running specified tests and multiple command line options, and improves testing efficiency.

Theargparsemoduleistherecommendedwaytohandlecommand-lineargumentsinPython,providingrobustparsing,typevalidation,helpmessages,anderrorhandling;usesys.argvforsimplecasesrequiringminimalsetup.

This article aims to explore the common problem of insufficient calculation accuracy of floating point numbers in Python and NumPy, and explains that its root cause lies in the representation limitation of standard 64-bit floating point numbers. For computing scenarios that require higher accuracy, the article will introduce and compare the usage methods, features and applicable scenarios of high-precision mathematical libraries such as mpmath, SymPy and gmpy to help readers choose the right tools to solve complex accuracy needs.

PyPDF2, pdfplumber and FPDF are the core libraries for Python to process PDF. Use PyPDF2 to perform text extraction, merging, splitting and encryption, such as reading the page through PdfReader and calling extract_text() to get content; pdfplumber is more suitable for retaining layout text extraction and table recognition, and supports extract_tables() to accurately capture table data; FPDF (recommended fpdf2) is used to generate PDF, and documents are built and output through add_page(), set_font() and cell(). When merging PDFs, PdfWriter's append() method can integrate multiple files

Import@contextmanagerfromcontextlibanddefineageneratorfunctionthatyieldsexactlyonce,wherecodebeforeyieldactsasenterandcodeafteryield(preferablyinfinally)actsas__exit__.2.Usethefunctioninawithstatement,wheretheyieldedvalueisaccessibleviaas,andthesetup

Getting the current time can be implemented in Python through the datetime module. 1. Use datetime.now() to obtain the local current time, 2. Use strftime("%Y-%m-%d%H:%M:%S") to format the output year, month, day, hour, minute and second, 3. Use datetime.now().time() to obtain only the time part, 4. It is recommended to use datetime.now(timezone.utc) to obtain UTC time, avoid using deprecated utcnow(), and daily operations can meet the needs by combining datetime.now() with formatted strings.
