PEP 526 as well as the specifcation states that all annotations in a class scope should be treated as instance variables unless marked with ClassVar
. Can this be modified to “When type checkers cannot statically determine if a class scoped annotation is an instance variable or classvariable, they should default to instance variable?”
This would change the typing behavior of:
class X:
something: int = 1
to be able to determine that X.something
is a classvariable. This is statically available information, but this may not always be available information statically, such as in stubs, ABCs, or protocols, so this is not a request to deprecate ClassVar
Edit: For anyone who isn’t reading the whole thread, this should require multiple changes to allow better inference without breaking people’s use cases.
- Inferring class variables
- Inferring instance variables
- Having an ability to specify both class and instance variables
- Having the ability to specify only a class or instance variable
Without static evidence that it must be only one or the other, the inference should continue allowing use as an instance variable. Presence of an identifier in slots should preclude classvar, presence in __init__
via self.identifier
should result in instance variable, type checkers should understand both.
examples here
class Error:
a: int = 1 # marks as a class var
__slots__ = ("a",) # marks as only an instance variable,
# error both statically and at runtime declaration
class X:
a: int = 1 # detect as ClassVar, non exclusively, matching runtime behavior
class CounterToX:
a: int # detect as instancevar, non-exclusive
# doesn't create a classvar at runtime.
class Y:
def __init__(self):
self.a: int = 2 # detect as instance var, non exclusively
class Z(Y, X): pass
Z.a # class var
Z().a # instance var
description of rules that would apply for consistency in subclasses here