Python. Use object attributes to annotate methods; Dynamically-defined type annotations

Question:

Python pseudocode

I want to dynamically annotate returning types for my methods. I want something that looks like this:

class Foo:
    def __init__(model: BaseModel):
        self.model = model
    
    def find_model(query) -> self.model:
        return db.get(query)

And then use it like this:

bar = Foo(model=MyModel) # pass actual class (that inherits from BaseModel), not its instance
obj = bar.find_model('my_query') # here I wanna get MyModel instance
obj. # here I wanna get list of all the available methods and attributes of MyModel instance in Pycharm

Java example

Basically, I want the user to define the returning type. In Java it looks like this:

Foo<Type> obj = new Foo<Type>

And is defined like this:

public class Foo<T> {

    private T t;
    
    public Foo(T value) {
        this.t = value;
    }
}

The question

Is there something similar to this in Python? I only found TypeVar and ClassVar, but Pycharm doesn’t suggest any methods or attributes when writing code

Asked By: Neykuratick

||

Answers:

You may want to see this answer: https://stackoverflow.com/a/59589910/16569581.

from typing import TypeVar, Generic, List

T = TypeVar('T')

class Foo(Generic[T]):
    def __init__(self) -> None:
        # You may want to create a list of T type items
        self.items: List[T] = []
    
    def find_model(query) -> List[T]: #return type as an object seems illogical to me
        return db.get(query)

And you can create objects and use the class functions as

# Construct an empty Foo[int] instance
obj = Foo[int]()
model = obj.find_model(query) 

If you don’t want to use predefined types of "typing" library, you may just use the class as in the code you wrote for the question. Because, in Python, functions don’t have to return predefined types of variables. Also, variables don’t have predefined types. So you don’t have to explicitly write the argument and return types write the code as:

class Foo:
    def __init__(self, table_model):
        self.model = table_model
    
    def find_model(query):
        return db.get(query)
Answered By: şamil arınç