Dart has "late variables" , swift has "Implicitly Unwrapped Optionals".
Does Python have something equivalent?
That means, something like myvar: Late[str] = None
that would indicate that I know that all access to myvar later on will be after it is initialized to a non-None value.
My use case:
@dataclass
class Flag:
name: Optional[str] = dataclasses.field(init=False, default=None)
default_value: Any
value_type: Type
description: str = ""
Flag.name is initialized by a "friend" class, and all access to Flag is through that friend class, so sure that outside of this module all access is not to an Optional, but to an actual str.
Python doesn't have declarations, only definitions. You can write something like
# *Looks* like a declaration, but does not create a variable
# named myvar, only annotates the name.
myvar: str
which tells any static type checker that myvar
, when finally used, will have a str
value, but doesn't actually create the variable yet. The annotation itself has no meaning at runtime, aside from possibly updating the global __annotations__
dict.
Later on, an initial assignment like myvar = "foo"
will be accepted by a static type checker, but an initial assignment like myvar = 1
will be rejected.
Such non-assigned annotated names are rarely necessary in Python. Their biggest use is in the body of a class
statement decorated by dataclass
, which allows you to define the instance attributes for instances of the class. (This information gets used when generating methods like __init__
.)
@dataclass
class Foo:
x: int
y: str = "foo"
z = 3
The type itself isn't terribly important; it's the presence of a type that causes dataclass
to generate an __init__
method like
def __init__(self, x: int, y: str = "foo"):
self.x = x
self.y = y
The unannotated name z
is taken as an ordinary class attribute.
I found the following not-the-best solution. I made the relevant member "protected" - changed it to _name, and wrapped it with a property.
The runtime check is only there to quiet down the type checker without shutting it down, and it does afford a little bit of extra protection if someone does misuse this, at a relatively small runtime speed code (that I don't care to optimize right now).
@dataclass
class Flag:
_name: Optional[str] = dataclasses.field(init=False, default=None)
default_value: Any
value_type: Type
description: str = ""
@property
def name(self) -> str:
if self._name is None:
raise RuntimeError("self._name not initialized")
return self._name
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With