Alexandru Sandu
Alexandru Sandu

Reputation: 143

Dynamic class level type hints in python?

I'm trying to provide type hinting in PyCharm dynamically for a specific class, meaning that one of its attributes has assigned a value during __init__, which on its turn is an object.

I've tried defining a class level type for the attribute, however the type of the attribute could be one of multiple classes, so I can't really point towards a specific type, but I would want to be able to have auto-complete on that attribute.

class Dynamic:
    def __init__(self):
        self.field1 = "field1"
        self.field2 = "field2"


class Reusable:
    def __init__(self, dynamics=None):
        if dynamics:
            self.values = dynamics
        else:
            self.values = "nothing"


dynamic_test = Dynamic()
test = Reusable(dynamics=dynamic_test)
print(test.values.)  # this is the place where auto-complete should take place

Obviously, the auto-complete does not take place. I tried things similar to

class Reusable:
    value_type = str  # type to-be-modified later
    values: value_type

    def __init__(self, dynamics=None):
        if dynamics:
            self.values = dynamics
        else:
            self.values = "nothing"
        Reusable.value_type = type(self.values)  # doesn't actually modify that so I won't have auto-complete based on type

I know that there's some possibilities involving handling the builtin __dir__ function, however I haven't gotten any luck with that either (not sure if dependent on PyCharm's auto-complete algorithm or not), nor any plugins have been developed in this direction.

Is there any way I can go around this one and have that auto-complete feature in this case?

Upvotes: 2

Views: 2882

Answers (1)

user2235698
user2235698

Reputation: 7579

Consider using type hints:

from typing import Generic, TypeVar, Union

T = TypeVar("T")


class Reusable(Generic[T]):
    values: Union[str, T]

    def __init__(self, dynamics: T = None):
        if dynamics:
            self.values = dynamics
        else:
            self.values = "nothing"

Here we marked Reusable as a class that could be parameterized with T.

By marking dynamics as T we are specified where to get exact value of T.

Union[str, T] means that values is either str or T.

See PEP-484 for more details.

Upvotes: 1

Related Questions