Home > Blockchain >  How can I mark the return type of a method based on the type of an argument in the object's con
How can I mark the return type of a method based on the type of an argument in the object's con

Time:12-29

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")
  • Related