On 9/30/23 13:00, Karsten Hilbert via Python-list wrote:
A type annotation isn't supposed to change what code does,
or so I thought:
#------------------------------------------------------------
class Borg:
_instances:dict = {}
def __new__(cls, *args, **kargs):
# look up subclass instance cache
if Borg._instances.get(cls) is None:
Borg._instances[cls] = object.__new__(cls)
return Borg._instances[cls]
class WorkingSingleton(Borg):
def __init__(self):
print(self.__class__.__name__, ':')
try:
self.already_initialized
print('already initialized')
return
except AttributeError:
print('initializing')
self.already_initialized = True
self.special_value = 42
class FailingSingleton(Borg):
def __init__(self):
print(self.__class__.__name__, ':')
try:
self.already_initialized:bool
print('already initialized')
return
except AttributeError:
print('initializing')
self.already_initialized = True
self.special_value = 42
s = WorkingSingleton()
print(s.special_value)
s = FailingSingleton()
print(s.special_value)
#------------------------------------------------------------
Notice how Working* and Failing differ in the type annotation
of self.already_initialized only.
What happens here is in the second case, the line is just recorded as a
variable annotation, and is not evaluated as a reference, as you're
expecting to happen, so it just goes right to the print call without
raising the exception. You could change your initializer like this:
def __init__(self):
print(self.__class__.__name__, ':')
self.already_initialized: bool
try:
self.already_initialized
print('already initialized')
return
The syntax description is here:
https://peps.python.org/pep-0526/#global-and-local-variable-annotations
--
https://mail.python.org/mailman/listinfo/python-list