So I have a simple wrapper class for making read-only attributes of a class.
class ReadOnly:
"""
Simple wrapper class to make an object read only
"""
def __init__(self, value) -> None:
self._value = value
def __get__(self, instance, owner):
return self._value
def __set__(self, value) -> None:
raise AttributeError("This value is read-only")
I use this elsewhere in my code to create read-only parameters. For example,
class Something:
def __init__(self) -> None:
self.attr = ReadOnly("A read-only string")
a = Something()
# Not allowed
a.attr = "This won't work"
The problem with this is that when I access a.attr
, its type is unknown, meaning my editor can't get autocompletions or type information, which could make it confusing for users of my code.
I understand that this is much easier to do using properties, but due to the nature of my program, doing that would result in hundreds of extra lines of repeated code.
As such, is there a way of getting the type of the value in the parameters of ReadOnly.__init__()
, so that I can explicitly mark the return value of ReadOnly.__get__()
as the same type?
I have tried using a TypeVar
from the typing module, and marking the parameter type with it and then letting it infer from there, but the type just comes out as T@__init__
.
The other alternative would be to annotate exact types in subclasses of the ReadOnly
type, for example
class ReadOnlyStr(ReadOnly):
def __init__(self, value: str) -> None:
super().__init__(value)
def __get__(self, instance, owner) -> str:
return super().__get__(instance, owner)
but this feels sorta janky, and would also quickly lead to repeated code if I had to do so with many types.
As such, what is the best way for me to tell Python the type of a variable given its type in a different function.
If it helps, I'm using VS Code with Pylance as my language server.
CodePudding user response:
Using Generics & TypeVar would be your best bet
from typing import TypeVar, Generic
PropType = TypeVar("PropType")
class ReadOnly(Generic[PropType]):
"""
Simple wrapper class to make an object read only
"""
def __init__(self, value: PropType):
self._value = value
def __get__(self, instance, owner) -> PropType:
return self._value
def __set__(self, value):
raise AttributeError("This value is read-only")