Home > Enterprise >  How to type hint dynamically created properties of a class
How to type hint dynamically created properties of a class

Time:10-20

def property_factory(n: int) -> property:
    getter = lambda self: return n
    return property(getter)

class Foo:
    number: int = property_factory(1)

The above code gives me the errror (line 6)

Expression of type "property" cannot be assigned to declared type int

How do I go about type hinting dynamically created properties?

CodePudding user response:

One possible option is to use Protocol:

from typing import Protocol, TypeVar, overload


T_co = TypeVar('T_co', covariant=True)


class ReadonlyProperty(Protocol[T_co]):

    @overload
    def __get__(self, instance: None, owner) -> property: ...

    @overload
    def __get__(self, instance, owner) -> T_co: ...

    def __get__(self, instance, owner) -> T_co | property: ...


def property_factory(n: int) -> ReadonlyProperty[int]:
    return property(lambda self: n)


class Foo:
    number: ReadonlyProperty[int] = property_factory(1)


n: int = Foo().number        # mypy pass
prop: property = Foo.number  # mypy pass
s: str = Foo().number        # Incompatible types in assignment (expression has type "int", variable has type "str") (28:9)
val: int = Foo.number        # Incompatible types in assignment (expression has type "property", variable has type "int") (29:11)

CodePudding user response:

Just change the return type to int instead of property.

But I suggest you to follow the classic approach:

class Foo:
    def __init__(self) -> None:
        self._property_factory: int = 0
        self.property_factory = 1
        number: int = self.property_factory

    @property   # getter
    def property_factory(self) -> int:
        return self._property_factory
    
    @property_factory.setter
    def property_factory(self, value: int) -> None:
        self._property_factory = value
  • Related