From 0ce955063f363a2eae888a5c561f07d70cee5593 Mon Sep 17 00:00:00 2001 From: JK <19386515+Johnny-Kao@users.noreply.github.com> Date: Fri, 2 Oct 2026 03:15:46 +0900 Subject: [PATCH 1/2] Improve astuple nested atomic sequence performance --- bench/test_benchmarks.py | 16 ++++++++++++++++ src/attr/_funcs.py | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/bench/test_benchmarks.py b/bench/test_benchmarks.py index 6adf21aa5..c71303306 100644 --- a/bench/test_benchmarks.py +++ b/bench/test_benchmarks.py @@ -177,6 +177,22 @@ def test_astuple_atomic(): at(c) +@attrs.define +class NestedAtomicFields: + sequence: list[int] = attrs.Factory(lambda: list(range(100))) + + +def test_astuple_nested_atomic(): + """ + Benchmark atomic values nested in a sequence. + """ + c = NestedAtomicFields() + at = attrs.astuple + + for _ in range(ROUNDS): + at(c) + + class TestCachedProperties: @attrs.define class Slotted: diff --git a/src/attr/_funcs.py b/src/attr/_funcs.py index d213efc22..c88c175a1 100644 --- a/src/attr/_funcs.py +++ b/src/attr/_funcs.py @@ -301,7 +301,7 @@ def astuple( tuple_factory=tuple_factory, retain_collection_types=retain, ) - if has(j.__class__) + if type(j) not in _ATOMIC_TYPES and has(j.__class__) else j ) for j in v From 0c504ac0426ec40d56d0e0de11eea5cee26c61f9 Mon Sep 17 00:00:00 2001 From: JK <19386515+Johnny-Kao@users.noreply.github.com> Date: Fri, 2 Oct 2026 03:17:18 +0900 Subject: [PATCH 2/2] Add changelog for astuple sequence optimization --- changelog.d/1636.change.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/1636.change.md diff --git a/changelog.d/1636.change.md b/changelog.d/1636.change.md new file mode 100644 index 000000000..f41d63260 --- /dev/null +++ b/changelog.d/1636.change.md @@ -0,0 +1 @@ +Improved `attrs.astuple()` performance for atomic values nested in sequences by avoiding unnecessary attrs-class detection.