Search code examples
pythonpython-typing

How to get property return type annotation?


I'm looking for a way to extract the return type annotation of a property from a class, e.g.:

class Test:
    @property
    def foo(self) -> int:
        return 1

print(return_type_extract(Test, 'foo')) # <class 'int'>

For standard methods this can be done like so:

import inspect
class Test:
    def foo(self) -> int:
        return 1

def return_type_extract(cls: type, method_name: str) -> type:
    method = getattr(cls, method_name)
    return inspect.signature(method).return_annotation

print(return_type_extract(Test, 'foo')) # <class 'int'>

This method however does not work for the @property decorator, as it raises an error inside inspect.signature. I've looked at an equivalent for properties in the inspect library, but so far no luck.


Solution

  • I hit the same issue and managed to find an answer, the key observation is here: https://docs.python.org/3/library/functions.html#property

    fget is a function for getting an attribute value

    This means signature return_annotation works, but we must apply it to properties' fget functions instead of directly to properties (as they encapsulate multiple functions)

    import dataclasses
    import inspect
    
    
    @dataclasses.dataclass
    class PropertyTest:
        a: int
    
        @property
        def b(self) -> float:
            return float(self.a)
    
    
    def test_property_return_type_from_class():
        property_return_type = prop_return_type_from_class(
            cls=PropertyTest,
            prop_name="b",
        )
        assert property_return_type is float
    
    
    def prop_return_type_from_class(
        *,
        prop_name: str,
        cls: type,
    ) -> type:
        prop = getattr(cls, prop_name)
        return_type = inspect.signature(prop.fget).return_annotation
        return return_type