classification
Title: dataclass defaults behave inconsistently for init=True/init=False when default is a descriptor
Type: behavior Stage:
Components: Library (Lib) Versions: Python 3.8, Python 3.7
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: eric.smith Nosy List: Kevin Shweh, eric.smith, levkivskyi
Priority: normal Keywords:

Created on 2019-11-30 23:53 by Kevin Shweh, last changed 2019-12-06 22:47 by levkivskyi.

Messages (1)
msg357669 - (view) Author: Kevin Shweh (Kevin Shweh) Date: 2019-11-30 23:53
The following code:

    from dataclasses import dataclass, field
    from typing import Callable
     
    @dataclass
    class Foo:
    	callback: Callable[[int], int] = lambda x: x**2
     
    @dataclass
    class Bar:
    	callback: Callable[[int], int] = field(init=False, default=lambda x: x**2)
     
    print(Foo().callback(2))
    print(Bar().callback(2))

prints 4 for the first print, but throws a TypeError for the second. This is because Foo() stores the default callback in the instance dict, while Bar() only has it in the class dict. Bar().callback triggers the descriptor protocol and produces a method object instead of the original callback.

There does not seem to be any indication in the dataclasses documentation that these fields will behave differently. It seems like they should behave the same, and/or the documentation should be clearer about how the default value/non-init field interaction behaves.
History
Date User Action Args
2019-12-06 22:47:09levkivskyisetnosy: + levkivskyi
2019-12-01 12:45:43eric.smithsetassignee: eric.smith
2019-12-01 03:40:07xtreaksetnosy: + eric.smith
2019-11-30 23:53:26Kevin Shwehcreate