Should dataclasses add__set__ (and possibly __get __) descriptors ?
Hello good morning. I've decided to open a discussion of a topic that I consider should be part of dataclasses, but not sure how suggestions work and many threads recommend to check python dev first so-. Anyways, at the moment that I write this message in python3.10.1, It happens that when making a class with the dataclasses module, this class can't actually be used in Multiple inheritance for Enum purposes, this is mostly to avoid code repetition by having to write the methods over again. Here's an example from dataclasses import dataclass from enum import Enum @dataclass class Foo: a: int = 0 class Entries(Foo, Enum): ENTRY1 = Foo(1) ENTRY2 = Foo(2) ENTRY3 = Foo(3) assert Entries.ENTRY1.a == 1 This raises AssertionError, due to the values not being defined at that point, as the class is currently just using the default paremeters. This is why I think it'd be essential to implement __set__ in the module. Currently there's a workaround to have this work, which is defining a __set__ but doing this, in more complex cases, can get to be very tedious and repetitive coding wise from dataclasses import dataclass from enum import Enum @dataclass class Foo: a: int = 0 def __set__(self, instance, value: int): instance.a = value class Entries(Foo, Enum): ENTRY1 = Foo(1) ENTRY2 = Foo(2) ENTRY3 = Foo(3) assert Entries.ENTRY1.a == 1 Have a great day, and hopefully this post enables a good discussion.
On 12/13/2021 1:43 AM, Vioshim wrote:
Hello good morning.
I've decided to open a discussion of a topic that I consider should be part of dataclasses, but not sure how suggestions work and many threads recommend to check python dev first so-.
Anyways, at the moment that I write this message in python3.10.1, It happens that when making a class with the dataclasses module, this class can't actually be used in Multiple inheritance for Enum purposes, this is mostly to avoid code repetition by having to write the methods over again.
Here's an example
from dataclasses import dataclass from enum import Enum
@dataclass class Foo: a: int = 0
class Entries(Foo, Enum): ENTRY1 = Foo(1) ENTRY2 = Foo(2) ENTRY3 = Foo(3)
assert Entries.ENTRY1.a == 1
This raises AssertionError, due to the values not being defined at that point, as the class is currently just using the default paremeters. This is why I think it'd be essential to implement __set__ in the module.
I don't understand what you're trying to achieve. Entries.ENTRY1.a is Foo object. Why would you expect it to be 1? And I don't understand why you're inheriting from Foo. What are you trying to accomplish with that? Could you explain in more detail why you're using this pattern? Eric
Currently there's a workaround to have this work, which is defining a __set__ but doing this, in more complex cases, can get to be very tedious and repetitive coding wise
from dataclasses import dataclass from enum import Enum
@dataclass class Foo: a: int = 0
def __set__(self, instance, value: int): instance.a = value
class Entries(Foo, Enum): ENTRY1 = Foo(1) ENTRY2 = Foo(2) ENTRY3 = Foo(3)
assert Entries.ENTRY1.a == 1
Have a great day, and hopefully this post enables a good discussion. _______________________________________________ Python-Dev mailing list -- python-dev@python.org To unsubscribe send an email to python-dev-leave@python.org https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/U2YDIU5T... Code of Conduct: http://python.org/psf/codeofconduct/
I'm also confused about what you are trying to achieve here. Note that: assert Entries.ENTRY1.value.a == 1 should work. But my main thought is that dataclasses are really just a way to auto-generate classes without having to write a bunch of boilerplate. So you example above is equivalent to: class Foo: def __init__(self, a=0): self.a = a Which behaves the same way when used the same way with Enum. So why should dataclasses be special in this particular way? -CHB -- Christopher Barker, PhD (Chris) Python Language Consulting - Teaching - Scientific Software Development - Desktop GUI and Web Development - wxPython, numpy, scipy, Cython
On Mon, Dec 13, 2021 at 06:43:27AM -0000, Vioshim wrote:
Anyways, at the moment that I write this message in python3.10.1, It happens that when making a class with the dataclasses module, this class can't actually be used in Multiple inheritance for Enum purposes, this is mostly to avoid code repetition by having to write the methods over again. [...] class Entries(Foo, Enum): ENTRY1 = Foo(1) ENTRY2 = Foo(2) ENTRY3 = Foo(3)
I think this may be what you are looking for:
class Entries(Foo, Enum): ... ENTRY1 = 1 ... ENTRY2 = 2 ... Entries.ENTRY1 Entries(a=1) Entries.ENTRY1.a 1 isinstance(Entries.ENTRY2, Foo) True
-- Steve
On 12/12/21 10:43 PM, Vioshim wrote:
Anyways, at the moment that I write this message in python3.10.1, It happens that when making a class with the dataclasses module, this class can't actually be used in Multiple inheritance for Enum purposes, this is mostly to avoid code repetition by having to write the methods over again.
Here's an example
from dataclasses import dataclass from enum import Enum
@dataclass class Foo: a: int = 0
class Entries(Foo, Enum): ENTRY1 = Foo(1) ENTRY2 = Foo(2) ENTRY3 = Foo(3)
assert Entries.ENTRY1.a == 1
This raises AssertionError, due to the values not being defined at that point,
What do you mean by this? Here is what I see: --> E = Entries.ENTRY1 --> E Entries(a=Foo(a=1)) --> E.value Foo(a=1) --> E.a Foo(a=1) Looks like both `value` and `a` are set. You're problem is that you said Entries is a Foo, and then you set Enum/Foo instances to also have Foo values. Here's what you need: class Entries(Foo, Enum): ENTRY1 = 1 ENTRY2 = 2 ENTRY3 = 3 Which gives us: --> e = Entries.ENTRY2 --> e Entries(a=2)
e.value 2 --> e.a 2 --> isinstance(e, Foo) True
-- ~Ethan~
Oh certainly that's the approach I was intending, basically wanted to make an enum that shares the methods that the original class can do, but this is quite helpful, I've been testing this approach and seems to work very well despite only working with *args, thanks a lot for the reply and everyone's feedback as now I have a full understanding on how this works. Have a great day.
participants (6)
-
Christopher Barker
-
Eric V. Smith
-
Ethan Furman
-
Steven D'Aprano
-
Vioshim
-
Vioshim