Open Codoscope opened 2 years ago
It’s easy to prevent 4.: just never ever use a mutable default value
class C:
x: list = None # do
y: list = [] # don't
a, b = C(), C()
a.x.append(1) # fails, since it is type None
a.x = [1]
print(a.x, "and", b.x)
## [1] and None
# otherwise same problem for a.y, b.y
While 1. Is the most readable and pleasing to me—and I would really like to be able to do so blindly—I think 3. is the safest and simplest choice. Otherwise there is a great confusion between the instances and class attributes, and we are dangerously close to case 4 with bad bugs. Moreover if you have many properties defined on your class, the whole point of grouping attributes makes little sense.
The (public) instance attributes should be listed in the class docstring with their types, à la Google. I think most IDEs do a good job at discovering objects attributes. Together with the class docstring this should be enough.
I'm with @lvignoli - I like the cleanliness of option 1., but I don't think it's worth the potential for confusion. I would go with 3. too.
My only qualm with making a style decision of this type is enforcing it. Would this come with a checker for CI? If not, I find it very hard as a reviewer to remember to check for this.
We had a discussion with @HGSilveri about where instance attributes should be type annotated. I dug a bit more on the subject, and here is what I can come with:
the cons is often circumvented by UTs, and it would be fixed with https://github.com/python/mypy/issues/4019
__init__
(what is done here): same pro in a weaker form, and identical cons__init__
:attributes could be both declared and defined at the class scope, which would be correct for static type checking, but would also create class attributes:
for more details, see:
The options 1 and 3 are probably the best ones between which we should choose (I would personnally go for the 1).
In all cases, I think we should avoid instance attribute declarations that are neither at the classe scope, neither inside
__init__
, but inside another method, because this basically cumulates cons of 1 and 3, and doesn't have any of the mentioned pros.