attrs
attrs copied to clipboard
evolve() and attr.ib(init=False, default="foo")
As pointed out in https://github.com/ericvsmith/dataclasses/issues/42#issuecomment-330198369 attr.evolve()
behaves rather weird if an attribute has
- init=False,
- a default/
__attrs_post_init__
, and - attribute(s) are modified on the instance.
The new resulting object will always have the default value.
I think I can live with that limitation if we document it and it's probably a good reason to resolve #207 with sticking assoc around with a better name?
Giving it further thought, the raison d'être for evolve are immutable objects…so I think it's fine to just document this edge case and leave it be?
import attr
@attr.s class MyDataClass: init_value: int = attr.ib(init=False) default_value: int = attr.ib(default=0)
def __attrs_post_init__(self):
self.init_value = 42 # Modifying an attribute in __attrs_post_init__
def evolve_example(): original_instance = MyDataClass() evolved_instance = attr.evolve(original_instance, init_value=100)
return evolved_instance
Documentation for the edge case
print(""" As pointed out in ericvsmith/dataclasses#42 (comment), attr.evolve() behaves in a specific way when an attribute has:
- init=False,
- a default/attrs_post_init, and
- attribute(s) are modified on the instance.
The new resulting object will always have the default value for that attribute. This behavior is because evolve is primarily designed for immutable objects.
Given the nature of evolve and its purpose for immutable objects, it is acceptable to document this edge case and leave it as is. """)
Example usage of attr.evolve()
evolved_obj = evolve_example() print(f"Evolved object: {evolved_obj}")