Claude-skill-registry enforcing-python-dunders
git clone https://github.com/majiayu000/claude-skill-registry
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/enforcing-python-dunders" ~/.claude/skills/majiayu000-claude-skill-registry-enforcing-python-dunders && rm -rf "$T"
skills/data/enforcing-python-dunders/SKILL.mdPython Dunder Method Enhancer
Overview
This skill ensures Python classes include appropriate, developer-friendly dunder methods. It prioritizes
__repr__ and __str__ but also adds other dunder methods when they meaningfully improve code clarity and ergonomics.
Files and Directories to Ignore
This skill must NOT modify:
Test directories:
,tests/
,test/__tests__/
Test file patterns:
,*_test.py
,test_*.pyconftest.py
Virtual environments:
,.venv/
,venv/
,env/.env/
Build artifacts and caches:
,build/
,dist/egg-info/
,.mypy_cache/
,.pytest_cache/__pycache__/
Auto-generated and vendor code:
,migrations/alembic/- Schema files, codegen outputs
,vendor/
,third_party/external/
Other:
(unless user explicitly requests)__init__.py
Core Guidelines
1. Prioritize __repr__
and __str__
__repr____str__- Always implement
: Provide a precise, unambiguous developer-oriented representation__repr__ - Implement
: Provide a readable, user-friendly representation__str__ - If only one can be implemented, implement
and let__repr__
fall back to it unless a distinct human-friendly format is genuinely needed__str__
requirements:__repr__
- Must be unambiguous and developer-focused
- Should ideally be valid Python that could recreate the object
- Format:
ClassName(attr1=value1, attr2=value2) - Use the ranking heuristics in
when selecting which fields to includereferences/field_ranking_heuristic.md - Consult the reference to distinguish between high-signal and low-signal fields
- Ensure that large business models produce concise, useful representations (2-5 high-value fields)
requirements:__str__
- User-friendly display format
- Can be less verbose than
__repr__ - Should be meaningful to end users
- Use the ranking heuristics in
when selecting which fields to includereferences/field_ranking_heuristic.md - Start with the primary display name, add 1-2 short qualifiers
- Avoid raw IDs unless essential for user identification
2. Dunder Methods That Improve Intuition
Operator Methods
Implement only when they make objects more natural to use:
- Arithmetic:
,__add__
,__sub__
,__mul__
, etc.__truediv__ - Comparison:
,__eq__
,__lt__
,__le__
,__gt____ge__
Container-Like Behavior
Only when the object logically represents a collection:
,__len__
,__getitem__
,__setitem__
,__delitem__
,__iter____contains__
Context Managers
Only when objects clearly manage a resource:
,__enter____exit__
3. Avoid Overuse & Complexity
Do NOT implement dunder methods that:
- Introduce surprising behavior
- Make objects harder to reason about
- Obscure real meaning or side effects
Follow the principle of least astonishment.
4. Don't Call Dunder Methods Directly
When writing code that uses objects with dunders:
- Prefer
overobj + otherobj.__add__(other) - Prefer
overlen(obj)obj.__len__() - Prefer
overobj[key]obj.__getitem__(key)
5. Use functools.total_ordering
When Appropriate
functools.total_orderingIf the class implements:
, AND__eq__- Exactly ONE of:
,__lt__
,__le__
,__gt____ge__
Then apply the
@total_ordering decorator to generate the rest automatically.
6. Document Dunder Implementations
Every implemented dunder method must include:
- A concise docstring describing expectations
- Any edge-case behavior
- The reasoning when overriding default semantics
Forbidden Dunder Methods
NEVER implement these methods. They control Python internals, object lifecycle, memory, class creation, async protocol machinery, pickling machinery, or interpreter-level behaviors.
Absolutely Forbidden
__new____init_subclass____class_getitem____getnewargs____getnewargs_ex____getstate____setstate____reduce____reduce_ex____del____prepare____mro_entries__
Async Protocol (Forbidden)
__await____aiter____anext____aenter____aexit__
Descriptor Protocol (Forbidden)
__get____set____delete____set_name__
Attribute Interception (Forbidden)
__getattr____getattribute____setattr____delattr____dir__
Hashing & Identity (Forbidden)
__hash__
(too easy to misuse)__bool__
Additional Python Guidelines
Type Hints Mandatory
All dunder methods must include explicit type hints.
Prefer Immutability When Possible
Favour
frozen=True dataclasses when mutation isn't required.
Use @dataclass
When Appropriate
@dataclassLet dataclasses supply basic dunder
__init__/__eq__/__repr__ unless custom behavior is needed.
Dataclass Conversion Rules
Do NOT automatically convert an existing non-dataclass into a dataclass.
Only convert to
@dataclass when ALL of these are true:
- The class is clearly a simple value object (fields only, no custom lifecycle)
- There is no inheritance, dynamic attributes, or metaclass use
- The user isn't relying on a custom
that would be overwritten__init__ - The class has no
definition__slots__ - There are no class-level validators or complex
requirements__post_init__
When in doubt, leave the class as-is and add dunder methods manually.
For new classes, prefer
@dataclass when:
- The class is explicitly a value object, AND
- It only stores attributes without complex lifecycle or invariants, AND
- No inheritance or dynamic attributes are involved
__slots__
Rules
__slots__Never add
__slots__ automatically.
Only add
__slots__ when:
- The user explicitly requests it, AND
- The class restricts attributes intentionally
Truthiness and Hashing
rules:__bool__
- Do NOT implement
unless the class has a single, obvious boolean meaning (e.g., success/failure wrapper, empty/non-empty collection)__bool__ - Never infer truthiness from length, internal state, or "seems falsy" heuristics
- When in doubt, omit it entirely—let Python's default behavior apply
rules:__hash__
- Never implement
for mutable classes__hash__ - If it's not clearly immutable (e.g.,
dataclass, all attributes are read-only), assume it is mutable and leavefrozen=True
alone__hash__ - If you implement
without__eq__
, Python automatically sets__hash__
(unhashable)—this is usually correct for mutable objects__hash__ = None
Copy/Clone Behavior
Do not implement
__copy__ or __deepcopy__ unless:
- The class manages external resources, OR
- The user explicitly requests custom clone semantics
No Side Effects in Representation Methods
__repr__ and __str__ must:
- Never mutate state
- Never perform I/O
- Never log
- Never compute expensive derived values
Use __post_init__
for Validation
__post_init__Validate invariants early and clearly in dataclasses.
Subclassing Rules
When adding or modifying dunder methods on a subclass of a widely used class (standard library or popular third-party), be extra conservative:
1. Default: Inherit, Don't Override
If the parent class already defines a dunder method, do NOT override it unless:
- There is a clear, domain-specific need, AND
- The new behavior remains compatible with the parent's documented expectations
2. Don't Change Core Operation Meanings
Never change the fundamental semantics of:
- Equality and ordering:
,__eq__
, etc.__lt__ - Hashing and identity:
,__hash____bool__ - Container behavior:
,__len__
,__getitem__
,__contains____iter__
3. __repr__
and __str__
on Subclasses
__repr____str__It is usually safe to provide a more informative
__repr__/__str__ on a subclass, as long as:
- They remain truthful and unambiguous
- They do not hide important information already shown by the parent
- They do not rely on side effects or heavy computation
- Prefer to call
orsuper().__repr__()
and extend/augment the resultsuper().__str__()
4. Always Call super()
When Overriding
super()If the subclass overrides a dunder that the parent already uses internally:
- Call
when appropriatesuper() - Preserve any pre-/post-conditions the base class expects
5. No New "Fake" Container or Context Behavior
Do NOT add container dunders or context manager dunders to a subclass unless the parent class already has that role.
6. Check Documentation Before Changing
For classes from the standard library or well-known packages (
dict, list, Path, BaseModel, DataFrame, etc.), treat their dunder behavior as part of a public contract.
7. When Unsure
If the correct behavior for a dunder on a subclass is unclear or potentially surprising:
- Avoid adding or modifying that dunder
- Leave a comment suggesting human review
Expected Output
When this skill makes changes, it should prefer:
- A unified diff patch (git-style) when editing files in place, OR
- A rewritten class definition with improved dunder methods, if the user is working in a single file snippet.
Avoid long narrative explanations unless explicitly requested by the user. Comments in code are acceptable when rationale is non-obvious.
Do NOT:
- Explain what dunder methods are
- Provide tutorial-style commentary
- Ask clarifying questions unless genuinely ambiguous
Do:
- Make the edit directly
- Add brief inline comments only where behavior is surprising or non-obvious
- Use type hints and docstrings as the primary documentation
When No Changes Are Needed
If a class already follows these dunder method guidelines, the skill should:
- Make no edits
- Return a brief confirmation (e.g., "Class already has appropriate dunder methods")
- Or output an empty diff
Do not rewrite existing correct code. Do not make style-only edits, reformat methods, or add unnecessary improvements when the class is already "good enough."
Examples (See references/
)
references/Read these files before implementing dunder methods:
| File | Purpose |
|---|---|
| Ideal classes with well-designed dunder methods. Pattern-match from these. |
| Anti-patterns to avoid. Check your work against these. |
| How to handle subclasses of common library types (, , etc.). |
| Quick reference for which dunders to implement, avoid, and how to reason about them. |
| Guidelines for selecting high-value fields to include in and . |
When implementing dunders, open the relevant example file first.
Field Ranking Reference
This skill uses an additional bundled reference document:
references/field_ranking_heuristic.md
This reference describes the domain-agnostic field ranking rules used when selecting which attributes to include in generated
__repr__ and __str__ methods.
When deciding which fields to display:
- Consult the reference file's priority ranking
- Favor identifiers, human-readable names, and canonical external handles
- Avoid printing large text fields, noisy metadata, or large collections
- Prefer short summaries for complex fields
The logic in this skill should defer to that reference whenever choosing or ranking fields for representations.
Quick Decision Tree
Is this Python source code (not tests/mocks/stubs)? ├─ No → Do NOT activate └─ Yes → Continue │ Does the class already have __repr__? ├─ No → Add __repr__ with type hints and docstring └─ Yes → Check if it follows best practices │ Should this class support comparison? ├─ Yes → Add __eq__ and one comparison op + @total_ordering └─ No → Skip comparison dunders │ Is this class container-like? ├─ Yes → Consider __len__, __getitem__, __iter__ └─ No → Do NOT add container dunders │ Does this class manage resources? ├─ Yes → Consider __enter__, __exit__ └─ No → Do NOT add context manager dunders
Summary
When invoked, this skill should:
- Inspect Python class definitions
- Add beneficial dunder methods (
,__repr__
, and others when appropriate)__str__ - Avoid touching or generating forbidden dunder methods
- Improve clarity and Pythonic ergonomics
- Modify only Python source code—not tests
- Produce clean, idiomatic, documented results