I am trying to decide between two styles, one using a class with only class variables and the other using dataclasses.
Class with class variables acting as data attributes:
class A1:
foo: str = ""
mut_list: list = [] # Note mutable default value
a = A1()
a.foo = "bar1"
a.mut_list = []
a.mut_list.append("baz1")
b = A1()
b.foo = "bar2"
b.mut_list = [] # Must set to empty list first before mutating
b.mut_list.append("baz2")
Versus making it a dataclass:
from dataclasses import dataclass, field
@dataclass
class A2:
foo: str = ""
mut_list: list = field(default_factory=list)
c = A2()
c.foo = "bar3"
c.mut_list.append("baz3")
d = A2()
d.foo = "bar4"
d.mut_list.append("baz4")
Which way is preferred and/or more clear to read?
In A1
, you are defining unnecessary class attributes that are shadowed by explicitly defined instance attributes. You could have just written
# You could even omit the annotated names altogether; they
# are only used for type-checking.
class A1:
foo: str
mut_list: list
a = A1()
a.foo = "bar1"
a.mut_list = ["baz1"]
In A2
, the dataclass uses the class attributes to automatically define various methods, one of which (__init__
) you should be but aren't using to avoid having to define the instance attributes explicitly.
from dataclasses import dataclass, field
@dataclass
class A2:
foo: str = ""
mut_list: list = field(default_factory=list)
c = A2("bar3", ["baz3"])
I would definitely prefer A2
over A1
, but only because it makes use of an __init__
method. You could just as easily add an __init__
method to A1
yourself to avoid having to assign to a.foo
and a.mut_list
after A1()
returns.