Skip to content

attrs.astuple() leaves performance on the table compared to operator.attrgetter #1129

Open
@raphCode

Description

@raphCode

I played around and found out that attrs.astuple is quite slow in comparison to using operator.attrgetter with all the field names.
Maybe the performance of attrs.astuple(recurse=False) can be improved, benefiting all library users?

Here is an example, save as .ipy file and open with ipython (I couldn't be bothered to fiddle with the timeit module manually):

from attrs import define
import attrs
import operator

@define
class A:
    a: int = 1
    b: int = 2
    c: int = 3
    d: int = 4
    e: int = 5
    f: int = 6

def faster_astuple(x):
    return operator.attrgetter(*(f.name for f in attrs.fields(type(x))))(x)

a = A()

print(attrs.astuple(a))
print(faster_astuple(a))

%timeit attrs.astuple(a, recurse=False)
%timeit faster_astuple(a)

output on my machine:

(1, 2, 3, 4, 5, 6)
(1, 2, 3, 4, 5, 6)
5.6 µs ± 159 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)
1.35 µs ± 28.4 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)

Speedup is around a factor of four.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions