Issue 43905: dataclasses.astuple (and .asdict) do deepcopy on all fields
Created on 2021-04-21 12:19 by mandolaerik, last changed 2022-04-11 14:59 by admin. This issue is now closed.
| Pull Requests | |||
|---|---|---|---|
| URL | Status | Linked | Edit |
| PR 26154 | merged | andrei.avk, 2021-05-15 22:19 | |
| PR 29851 | merged | miss-islington, 2021-11-29 18:10 | |
| PR 29852 | merged | miss-islington, 2021-11-29 18:10 | |
| Messages (14) | |||
|---|---|---|---|
| msg391516 - (view) | Author: Erik Carstensen (mandolaerik) | Date: 2021-04-21 12:19 | |
It seems that the 'dataclass.astuple' function does a deepcopy of all fields. This is not documented. Two problems:
1. Dictionary keys that rely on object identity are ruined:
import dataclasses
@dataclasses.dataclass
class Foo:
key: object
key = object()
lut = {key: 5}
(y,) = dataclasses.astuple(Foo(x))
# KeyError
lut[y]
2. dataclasses can only be converted to a tuple if all fields are serializable:
import dataclasses
@dataclasses.dataclass
class Foo:
f: object
foo = Foo(open('test.py'))
dataclasses.astuple(foo)
->
TypeError: cannot pickle '_io.TextIOWrapper' object
In my use case, I just want a list of all fields. I can do the following as a workaround:
(getattr(foo, field.name) for field in dataclasses.fields(foo))
Tested on Python 3.8.7 and 3.7.9.
|
|||
| msg391518 - (view) | Author: Eric V. Smith (eric.smith) * ![]() |
Date: 2021-04-21 12:25 | |
Unfortunately this can't be changed, although I suppose it should be documented. In general I think this API was a mistake, and should not have been added. There are just too many cases where it doesn't do what you want, or where it fails. I'd like to deprecate it and remove it (along with asdict), but I fear that would be too disruptive. Your approach seems reasonable to me for your use case. |
|||
| msg391519 - (view) | Author: Serhiy Storchaka (serhiy.storchaka) * ![]() |
Date: 2021-04-21 12:52 | |
Why deepcopy is used at all? It is a very specific feature which should not be used by default. If you want to make a deep copy of fields, you can call copy.deepcopy() explicitly.
copy.deepcopy(dataclasses.astuple(obj))
or
dataclasses.astuple(copy.deepcopy(obj))
|
|||
| msg391520 - (view) | Author: Eric V. Smith (eric.smith) * ![]() |
Date: 2021-04-21 13:20 | |
The reason for the deep copying was to support changing a hierarchy of dataclasses into something that could be JSON serialized. But it didn't really work out. It recurses into dataclasses, namedtuples, lists, tuples, and dicts, and deep copies everything else. As I said, it's a design flaw. |
|||
| msg394015 - (view) | Author: Erik Carstensen (mandolaerik) | Date: 2021-05-20 11:43 | |
Would it make sense to make dataclasses iterable, like so?
def __iter__(self):
return (getattr(self, field.name) for field in fields(self))
With that in place, deprecating astuple would maybe be less disruptive?
|
|||
| msg394019 - (view) | Author: Eric V. Smith (eric.smith) * ![]() |
Date: 2021-05-20 12:10 | |
No, iteration is explicitly a non-goal of PEP 557. See the section on namedtuple for why: https://www.python.org/dev/peps/pep-0557/#why-not-just-use-namedtuple |
|||
| msg396284 - (view) | Author: Andrei Kulakov (andrei.avk) * ![]() |
Date: 2021-06-21 19:42 | |
I've added a PR here: https://github.com/python/cpython/pull/26154 |
|||
| msg407241 - (view) | Author: Andrei Kulakov (andrei.avk) * ![]() |
Date: 2021-11-29 01:48 | |
Eric: I've closed a similar issue about asdict() and now updating the title to keep track of both in this issue. Let me know if you want to keep them separate instead. |
|||
| msg407243 - (view) | Author: Eric V. Smith (eric.smith) * ![]() |
Date: 2021-11-29 02:35 | |
I think it's find to address both of these here. |
|||
| msg407306 - (view) | Author: miss-islington (miss-islington) | Date: 2021-11-29 18:10 | |
New changeset c1f93f0d378958dfae4f24aad0c0088e3e04e403 by andrei kulakov in branch 'main': bpo-43905: Expand dataclasses.astuple() and asdict() docs (GH-26154) https://github.com/python/cpython/commit/c1f93f0d378958dfae4f24aad0c0088e3e04e403 |
|||
| msg407310 - (view) | Author: miss-islington (miss-islington) | Date: 2021-11-29 18:30 | |
New changeset 376b24e4f69cba53bae9856e9d076af47bb2b6c6 by Miss Islington (bot) in branch '3.9': bpo-43905: Expand dataclasses.astuple() and asdict() docs (GH-26154) https://github.com/python/cpython/commit/376b24e4f69cba53bae9856e9d076af47bb2b6c6 |
|||
| msg407311 - (view) | Author: miss-islington (miss-islington) | Date: 2021-11-29 18:33 | |
New changeset 32f1491a9770b7f2989507ecf8f13ef35dd95b0b by Miss Islington (bot) in branch '3.10': bpo-43905: Expand dataclasses.astuple() and asdict() docs (GH-26154) https://github.com/python/cpython/commit/32f1491a9770b7f2989507ecf8f13ef35dd95b0b |
|||
| msg407314 - (view) | Author: Eric V. Smith (eric.smith) * ![]() |
Date: 2021-11-29 18:34 | |
Thanks, @andrei.avk! |
|||
| msg407316 - (view) | Author: Andrei Kulakov (andrei.avk) * ![]() |
Date: 2021-11-29 18:44 | |
Thank you for reviewing Eric! |
|||
| History | |||
|---|---|---|---|
| Date | User | Action | Args |
| 2022-04-11 14:59:44 | admin | set | github: 88071 |
| 2021-11-29 18:44:26 | andrei.avk | set | messages: + msg407316 |
| 2021-11-29 18:34:32 | eric.smith | set | status: open -> closed type: behavior messages: + msg407314 resolution: fixed |
| 2021-11-29 18:33:04 | miss-islington | set | messages: + msg407311 |
| 2021-11-29 18:30:46 | miss-islington | set | messages: + msg407310 |
| 2021-11-29 18:10:44 | miss-islington | set | pull_requests: + pull_request28081 |
| 2021-11-29 18:10:41 | miss-islington | set | pull_requests: + pull_request28080 |
| 2021-11-29 18:10:40 | miss-islington | set | nosy:
+ miss-islington messages: + msg407306 |
| 2021-11-29 02:35:27 | eric.smith | set | messages:
+ msg407243 components: + Documentation, - Library (Lib) versions: + Python 3.9, Python 3.10, Python 3.11, - Python 3.7, Python 3.8 |
| 2021-11-29 01:48:56 | andrei.avk | set | messages:
+ msg407241 title: dataclasses.astuple does deepcopy on all fields -> dataclasses.astuple (and .asdict) do deepcopy on all fields |
| 2021-11-28 19:17:43 | andrei.avk | link | issue44695 superseder |
| 2021-06-21 19:42:03 | andrei.avk | set | messages: + msg396284 |
| 2021-05-20 12:10:46 | eric.smith | set | messages: + msg394019 |
| 2021-05-20 11:43:00 | mandolaerik | set | messages: + msg394015 |
| 2021-05-15 22:19:51 | andrei.avk | set | keywords:
+ patch nosy: + andrei.avk pull_requests:
+ pull_request24788 |
| 2021-04-21 13:20:47 | eric.smith | set | messages: + msg391520 |
| 2021-04-21 12:52:41 | serhiy.storchaka | set | nosy:
+ serhiy.storchaka messages: + msg391519 |
| 2021-04-21 12:25:03 | eric.smith | set | assignee: eric.smith messages:
+ msg391518 |
| 2021-04-21 12:19:17 | mandolaerik | create | |

